mirror of
https://github.com/lldap/lldap.git
synced 2024-11-25 00:50:55 +00:00
server: return custom attributes when asked for all attributes
This commit is contained in:
parent
df188ee83f
commit
a190fe7ddf
4 changed files with 210 additions and 180 deletions
|
@ -7,31 +7,28 @@ use tracing::{debug, instrument, warn};
|
||||||
use crate::domain::{
|
use crate::domain::{
|
||||||
deserialize::deserialize_attribute_value,
|
deserialize::deserialize_attribute_value,
|
||||||
handler::{GroupListerBackendHandler, GroupRequestFilter},
|
handler::{GroupListerBackendHandler, GroupRequestFilter},
|
||||||
ldap::error::LdapError,
|
ldap::{
|
||||||
|
error::{LdapError, LdapResult},
|
||||||
|
utils::{
|
||||||
|
expand_attribute_wildcards, get_custom_attribute,
|
||||||
|
get_group_id_from_distinguished_name_or_plain_name,
|
||||||
|
get_user_id_from_distinguished_name_or_plain_name, map_group_field, ExpandedAttributes,
|
||||||
|
GroupFieldType, LdapInfo,
|
||||||
|
},
|
||||||
|
},
|
||||||
schema::{PublicSchema, SchemaGroupAttributeExtractor},
|
schema::{PublicSchema, SchemaGroupAttributeExtractor},
|
||||||
types::{AttributeName, AttributeType, Group, LdapObjectClass, UserId, Uuid},
|
types::{AttributeName, AttributeType, Group, LdapObjectClass, UserId, Uuid},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
|
||||||
error::LdapResult,
|
|
||||||
utils::{
|
|
||||||
expand_attribute_wildcards, get_custom_attribute,
|
|
||||||
get_group_id_from_distinguished_name_or_plain_name,
|
|
||||||
get_user_id_from_distinguished_name_or_plain_name, map_group_field, GroupFieldType,
|
|
||||||
LdapInfo,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn get_group_attribute(
|
pub fn get_group_attribute(
|
||||||
group: &Group,
|
group: &Group,
|
||||||
base_dn_str: &str,
|
base_dn_str: &str,
|
||||||
attribute: &str,
|
attribute: &AttributeName,
|
||||||
user_filter: &Option<UserId>,
|
user_filter: &Option<UserId>,
|
||||||
ignored_group_attributes: &[AttributeName],
|
ignored_group_attributes: &[AttributeName],
|
||||||
schema: &PublicSchema,
|
schema: &PublicSchema,
|
||||||
) -> Option<Vec<Vec<u8>>> {
|
) -> Option<Vec<Vec<u8>>> {
|
||||||
let attribute = AttributeName::from(attribute);
|
let attribute_values = match map_group_field(attribute, schema) {
|
||||||
let attribute_values = match map_group_field(&attribute, schema) {
|
|
||||||
GroupFieldType::ObjectClass => {
|
GroupFieldType::ObjectClass => {
|
||||||
let mut classes = vec![b"groupOfUniqueNames".to_vec()];
|
let mut classes = vec![b"groupOfUniqueNames".to_vec()];
|
||||||
classes.extend(
|
classes.extend(
|
||||||
|
@ -74,12 +71,12 @@ pub fn get_group_attribute(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if ignored_group_attributes.contains(&attribute) {
|
if ignored_group_attributes.contains(attribute) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
get_custom_attribute::<SchemaGroupAttributeExtractor>(
|
get_custom_attribute::<SchemaGroupAttributeExtractor>(
|
||||||
&group.attributes,
|
&group.attributes,
|
||||||
&attribute,
|
attribute,
|
||||||
schema,
|
schema,
|
||||||
).or_else(||{warn!(
|
).or_else(||{warn!(
|
||||||
r#"Ignoring unrecognized group attribute: {}\n\
|
r#"Ignoring unrecognized group attribute: {}\n\
|
||||||
|
@ -105,33 +102,42 @@ const ALL_GROUP_ATTRIBUTE_KEYS: &[&str] = &[
|
||||||
"entryuuid",
|
"entryuuid",
|
||||||
];
|
];
|
||||||
|
|
||||||
fn expand_group_attribute_wildcards(attributes: &[String]) -> Vec<&str> {
|
fn expand_group_attribute_wildcards(attributes: &[String]) -> ExpandedAttributes {
|
||||||
expand_attribute_wildcards(attributes, ALL_GROUP_ATTRIBUTE_KEYS)
|
expand_attribute_wildcards(attributes, ALL_GROUP_ATTRIBUTE_KEYS)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_ldap_search_group_result_entry(
|
fn make_ldap_search_group_result_entry(
|
||||||
group: Group,
|
group: Group,
|
||||||
base_dn_str: &str,
|
base_dn_str: &str,
|
||||||
expanded_attributes: &[&str],
|
mut expanded_attributes: ExpandedAttributes,
|
||||||
user_filter: &Option<UserId>,
|
user_filter: &Option<UserId>,
|
||||||
ignored_group_attributes: &[AttributeName],
|
ignored_group_attributes: &[AttributeName],
|
||||||
schema: &PublicSchema,
|
schema: &PublicSchema,
|
||||||
) -> LdapSearchResultEntry {
|
) -> LdapSearchResultEntry {
|
||||||
|
if expanded_attributes.include_custom_attributes {
|
||||||
|
expanded_attributes.attribute_keys.extend(
|
||||||
|
group
|
||||||
|
.attributes
|
||||||
|
.iter()
|
||||||
|
.map(|a| (a.name.clone(), a.name.to_string())),
|
||||||
|
);
|
||||||
|
}
|
||||||
LdapSearchResultEntry {
|
LdapSearchResultEntry {
|
||||||
dn: format!("cn={},ou=groups,{}", group.display_name, base_dn_str),
|
dn: format!("cn={},ou=groups,{}", group.display_name, base_dn_str),
|
||||||
attributes: expanded_attributes
|
attributes: expanded_attributes
|
||||||
.iter()
|
.attribute_keys
|
||||||
.filter_map(|a| {
|
.into_iter()
|
||||||
|
.filter_map(|(attribute, name)| {
|
||||||
let values = get_group_attribute(
|
let values = get_group_attribute(
|
||||||
&group,
|
&group,
|
||||||
base_dn_str,
|
base_dn_str,
|
||||||
a,
|
&attribute,
|
||||||
user_filter,
|
user_filter,
|
||||||
ignored_group_attributes,
|
ignored_group_attributes,
|
||||||
schema,
|
schema,
|
||||||
)?;
|
)?;
|
||||||
Some(LdapPartialAttribute {
|
Some(LdapPartialAttribute {
|
||||||
atype: a.to_string(),
|
atype: name,
|
||||||
vals: values,
|
vals: values,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -295,7 +301,7 @@ pub fn convert_groups_to_ldap_op<'a>(
|
||||||
LdapOp::SearchResultEntry(make_ldap_search_group_result_entry(
|
LdapOp::SearchResultEntry(make_ldap_search_group_result_entry(
|
||||||
g,
|
g,
|
||||||
&ldap_info.base_dn_str,
|
&ldap_info.base_dn_str,
|
||||||
expanded_attributes.as_ref().unwrap(),
|
expanded_attributes.clone().unwrap(),
|
||||||
user_filter,
|
user_filter,
|
||||||
&ldap_info.ignored_group_attributes,
|
&ldap_info.ignored_group_attributes,
|
||||||
schema,
|
schema,
|
||||||
|
|
|
@ -12,8 +12,8 @@ use crate::domain::{
|
||||||
utils::{
|
utils::{
|
||||||
expand_attribute_wildcards, get_custom_attribute,
|
expand_attribute_wildcards, get_custom_attribute,
|
||||||
get_group_id_from_distinguished_name_or_plain_name,
|
get_group_id_from_distinguished_name_or_plain_name,
|
||||||
get_user_id_from_distinguished_name_or_plain_name, map_user_field, LdapInfo,
|
get_user_id_from_distinguished_name_or_plain_name, map_user_field, ExpandedAttributes,
|
||||||
UserFieldType,
|
LdapInfo, UserFieldType,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
schema::{PublicSchema, SchemaUserAttributeExtractor},
|
schema::{PublicSchema, SchemaUserAttributeExtractor},
|
||||||
|
@ -25,14 +25,13 @@ use crate::domain::{
|
||||||
|
|
||||||
pub fn get_user_attribute(
|
pub fn get_user_attribute(
|
||||||
user: &User,
|
user: &User,
|
||||||
attribute: &str,
|
attribute: &AttributeName,
|
||||||
base_dn_str: &str,
|
base_dn_str: &str,
|
||||||
groups: Option<&[GroupDetails]>,
|
groups: Option<&[GroupDetails]>,
|
||||||
ignored_user_attributes: &[AttributeName],
|
ignored_user_attributes: &[AttributeName],
|
||||||
schema: &PublicSchema,
|
schema: &PublicSchema,
|
||||||
) -> Option<Vec<Vec<u8>>> {
|
) -> Option<Vec<Vec<u8>>> {
|
||||||
let attribute = AttributeName::from(attribute);
|
let attribute_values = match map_user_field(attribute, schema) {
|
||||||
let attribute_values = match map_user_field(&attribute, schema) {
|
|
||||||
UserFieldType::ObjectClass => {
|
UserFieldType::ObjectClass => {
|
||||||
let mut classes = vec![
|
let mut classes = vec![
|
||||||
b"inetOrgPerson".to_vec(),
|
b"inetOrgPerson".to_vec(),
|
||||||
|
@ -93,12 +92,12 @@ pub fn get_user_attribute(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if ignored_user_attributes.contains(&attribute) {
|
if ignored_user_attributes.contains(attribute) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
get_custom_attribute::<SchemaUserAttributeExtractor>(
|
get_custom_attribute::<SchemaUserAttributeExtractor>(
|
||||||
&user.attributes,
|
&user.attributes,
|
||||||
&attribute,
|
attribute,
|
||||||
schema,
|
schema,
|
||||||
)
|
)
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
|
@ -134,27 +133,34 @@ const ALL_USER_ATTRIBUTE_KEYS: &[&str] = &[
|
||||||
fn make_ldap_search_user_result_entry(
|
fn make_ldap_search_user_result_entry(
|
||||||
user: User,
|
user: User,
|
||||||
base_dn_str: &str,
|
base_dn_str: &str,
|
||||||
expanded_attributes: &[&str],
|
mut expanded_attributes: ExpandedAttributes,
|
||||||
groups: Option<&[GroupDetails]>,
|
groups: Option<&[GroupDetails]>,
|
||||||
ignored_user_attributes: &[AttributeName],
|
ignored_user_attributes: &[AttributeName],
|
||||||
schema: &PublicSchema,
|
schema: &PublicSchema,
|
||||||
) -> LdapSearchResultEntry {
|
) -> LdapSearchResultEntry {
|
||||||
let dn = format!("uid={},ou=people,{}", user.user_id.as_str(), base_dn_str);
|
if expanded_attributes.include_custom_attributes {
|
||||||
|
expanded_attributes.attribute_keys.extend(
|
||||||
|
user.attributes
|
||||||
|
.iter()
|
||||||
|
.map(|a| (a.name.clone(), a.name.to_string())),
|
||||||
|
);
|
||||||
|
}
|
||||||
LdapSearchResultEntry {
|
LdapSearchResultEntry {
|
||||||
dn,
|
dn: format!("uid={},ou=people,{}", user.user_id.as_str(), base_dn_str),
|
||||||
attributes: expanded_attributes
|
attributes: expanded_attributes
|
||||||
.iter()
|
.attribute_keys
|
||||||
.filter_map(|a| {
|
.into_iter()
|
||||||
|
.filter_map(|(attribute, name)| {
|
||||||
let values = get_user_attribute(
|
let values = get_user_attribute(
|
||||||
&user,
|
&user,
|
||||||
a,
|
&attribute,
|
||||||
base_dn_str,
|
base_dn_str,
|
||||||
groups,
|
groups,
|
||||||
ignored_user_attributes,
|
ignored_user_attributes,
|
||||||
schema,
|
schema,
|
||||||
)?;
|
)?;
|
||||||
Some(LdapPartialAttribute {
|
Some(LdapPartialAttribute {
|
||||||
atype: a.to_string(),
|
atype: name,
|
||||||
vals: values,
|
vals: values,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -295,7 +301,7 @@ fn convert_user_filter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_user_attribute_wildcards(attributes: &[String]) -> Vec<&str> {
|
fn expand_user_attribute_wildcards(attributes: &[String]) -> ExpandedAttributes {
|
||||||
expand_attribute_wildcards(attributes, ALL_USER_ATTRIBUTE_KEYS)
|
expand_attribute_wildcards(attributes, ALL_USER_ATTRIBUTE_KEYS)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +340,7 @@ pub fn convert_users_to_ldap_op<'a>(
|
||||||
LdapOp::SearchResultEntry(make_ldap_search_user_result_entry(
|
LdapOp::SearchResultEntry(make_ldap_search_user_result_entry(
|
||||||
u.user,
|
u.user,
|
||||||
&ldap_info.base_dn_str,
|
&ldap_info.base_dn_str,
|
||||||
expanded_attributes.as_ref().unwrap(),
|
expanded_attributes.clone().unwrap(),
|
||||||
u.groups.as_deref(),
|
u.groups.as_deref(),
|
||||||
&ldap_info.ignored_user_attributes,
|
&ldap_info.ignored_user_attributes,
|
||||||
schema,
|
schema,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use chrono::{NaiveDateTime, TimeZone};
|
use chrono::{NaiveDateTime, TimeZone};
|
||||||
use itertools::Itertools;
|
|
||||||
use ldap3_proto::{proto::LdapSubstringFilter, LdapResultCode};
|
use ldap3_proto::{proto::LdapSubstringFilter, LdapResultCode};
|
||||||
use tracing::{debug, instrument, warn};
|
use tracing::{debug, instrument, warn};
|
||||||
|
|
||||||
|
@ -137,30 +138,39 @@ pub fn get_group_id_from_distinguished_name_or_plain_name(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ExpandedAttributes {
|
||||||
|
// Lowercase name to original name.
|
||||||
|
pub attribute_keys: BTreeMap<AttributeName, String>,
|
||||||
|
pub include_custom_attributes: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(skip(all_attribute_keys), level = "debug")]
|
#[instrument(skip(all_attribute_keys), level = "debug")]
|
||||||
pub fn expand_attribute_wildcards<'a>(
|
pub fn expand_attribute_wildcards(
|
||||||
ldap_attributes: &'a [String],
|
ldap_attributes: &[String],
|
||||||
all_attribute_keys: &'a [&'static str],
|
all_attribute_keys: &[&'static str],
|
||||||
) -> Vec<&'a str> {
|
) -> ExpandedAttributes {
|
||||||
let extra_attributes =
|
let mut include_custom_attributes = false;
|
||||||
|
let mut attributes_out: BTreeMap<_, _> = ldap_attributes
|
||||||
|
.iter()
|
||||||
|
.filter(|&s| s != "*" && s != "+" && s != "1.1")
|
||||||
|
.map(|s| (AttributeName::from(s), s.to_string()))
|
||||||
|
.collect();
|
||||||
|
attributes_out.extend(
|
||||||
if ldap_attributes.iter().any(|x| x == "*") || ldap_attributes.is_empty() {
|
if ldap_attributes.iter().any(|x| x == "*") || ldap_attributes.is_empty() {
|
||||||
|
include_custom_attributes = true;
|
||||||
all_attribute_keys
|
all_attribute_keys
|
||||||
} else {
|
} else {
|
||||||
&[]
|
&[]
|
||||||
}
|
}
|
||||||
.iter()
|
.iter()
|
||||||
.copied();
|
.map(|&s| (AttributeName::from(s), s.to_string())),
|
||||||
let attributes_out = ldap_attributes
|
);
|
||||||
.iter()
|
debug!(?attributes_out);
|
||||||
.map(|s| s.as_str())
|
ExpandedAttributes {
|
||||||
.filter(|&s| s != "*" && s != "+" && s != "1.1");
|
attribute_keys: attributes_out,
|
||||||
|
include_custom_attributes,
|
||||||
// Deduplicate, preserving order
|
}
|
||||||
let resolved_attributes = itertools::chain(attributes_out, extra_attributes)
|
|
||||||
.unique_by(|a| a.to_ascii_lowercase())
|
|
||||||
.collect_vec();
|
|
||||||
debug!(?resolved_attributes);
|
|
||||||
resolved_attributes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_subtree(subtree: &[(String, String)], base_tree: &[(String, String)]) -> bool {
|
pub fn is_subtree(subtree: &[(String, String)], base_tree: &[(String, String)]) -> bool {
|
||||||
|
|
|
@ -775,13 +775,13 @@ impl<Backend: BackendHandler + LoginHandler + OpaqueHandler> LdapHandler<Backend
|
||||||
message: "Too many search results".to_string(),
|
message: "Too many search results".to_string(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
let requested_attribute = AttributeName::from(&request.atype);
|
||||||
match entries.first() {
|
match entries.first() {
|
||||||
Some(LdapOp::SearchResultEntry(entry)) => {
|
Some(LdapOp::SearchResultEntry(entry)) => {
|
||||||
let available = entry
|
let available = entry.attributes.iter().any(|attr| {
|
||||||
.attributes
|
AttributeName::from(&attr.atype) == requested_attribute
|
||||||
.iter()
|
&& attr.vals.contains(&request.val)
|
||||||
.any(|attr| attr.atype == request.atype && attr.vals.contains(&request.val));
|
});
|
||||||
Ok(vec![LdapOp::CompareResult(LdapResultOp {
|
Ok(vec![LdapOp::CompareResult(LdapResultOp {
|
||||||
code: if available {
|
code: if available {
|
||||||
LdapResultCode::CompareTrue
|
LdapResultCode::CompareTrue
|
||||||
|
@ -1287,32 +1287,6 @@ mod tests {
|
||||||
LdapOp::SearchResultEntry(LdapSearchResultEntry {
|
LdapOp::SearchResultEntry(LdapSearchResultEntry {
|
||||||
dn: "uid=bob_1,ou=people,dc=example,dc=com".to_string(),
|
dn: "uid=bob_1,ou=people,dc=example,dc=com".to_string(),
|
||||||
attributes: vec![
|
attributes: vec![
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "objectClass".to_string(),
|
|
||||||
vals: vec![
|
|
||||||
b"inetOrgPerson".to_vec(),
|
|
||||||
b"posixAccount".to_vec(),
|
|
||||||
b"mailAccount".to_vec(),
|
|
||||||
b"person".to_vec(),
|
|
||||||
b"customUserClass".to_vec(),
|
|
||||||
]
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "uid".to_string(),
|
|
||||||
vals: vec![b"bob_1".to_vec()]
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "mail".to_string(),
|
|
||||||
vals: vec![b"bob@bobmail.bob".to_vec()]
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "givenName".to_string(),
|
|
||||||
vals: vec!["Bôb".to_string().into_bytes()]
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "sn".to_string(),
|
|
||||||
vals: vec!["Böbberson".to_string().into_bytes()]
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "cn".to_string(),
|
atype: "cn".to_string(),
|
||||||
vals: vec!["Bôb Böbberson".to_string().into_bytes()]
|
vals: vec!["Bôb Böbberson".to_string().into_bytes()]
|
||||||
|
@ -1325,11 +1299,14 @@ mod tests {
|
||||||
atype: "entryUuid".to_string(),
|
atype: "entryUuid".to_string(),
|
||||||
vals: vec![b"698e1d5f-7a40-3151-8745-b9b8a37839da".to_vec()]
|
vals: vec![b"698e1d5f-7a40-3151-8745-b9b8a37839da".to_vec()]
|
||||||
},
|
},
|
||||||
],
|
LdapPartialAttribute {
|
||||||
}),
|
atype: "givenName".to_string(),
|
||||||
LdapOp::SearchResultEntry(LdapSearchResultEntry {
|
vals: vec!["Bôb".to_string().into_bytes()]
|
||||||
dn: "uid=jim,ou=people,dc=example,dc=com".to_string(),
|
},
|
||||||
attributes: vec![
|
LdapPartialAttribute {
|
||||||
|
atype: "mail".to_string(),
|
||||||
|
vals: vec![b"bob@bobmail.bob".to_vec()]
|
||||||
|
},
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "objectClass".to_string(),
|
atype: "objectClass".to_string(),
|
||||||
vals: vec![
|
vals: vec![
|
||||||
|
@ -1340,22 +1317,19 @@ mod tests {
|
||||||
b"customUserClass".to_vec(),
|
b"customUserClass".to_vec(),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "uid".to_string(),
|
|
||||||
vals: vec![b"jim".to_vec()]
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "mail".to_string(),
|
|
||||||
vals: vec![b"jim@cricket.jim".to_vec()]
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "givenName".to_string(),
|
|
||||||
vals: vec![b"Jim".to_vec()]
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "sn".to_string(),
|
atype: "sn".to_string(),
|
||||||
vals: vec![b"Cricket".to_vec()]
|
vals: vec!["Böbberson".to_string().into_bytes()]
|
||||||
},
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "uid".to_string(),
|
||||||
|
vals: vec![b"bob_1".to_vec()]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
LdapOp::SearchResultEntry(LdapSearchResultEntry {
|
||||||
|
dn: "uid=jim,ou=people,dc=example,dc=com".to_string(),
|
||||||
|
attributes: vec![
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "cn".to_string(),
|
atype: "cn".to_string(),
|
||||||
vals: vec![b"Jimminy Cricket".to_vec()]
|
vals: vec![b"Jimminy Cricket".to_vec()]
|
||||||
|
@ -1368,10 +1342,36 @@ mod tests {
|
||||||
atype: "entryUuid".to_string(),
|
atype: "entryUuid".to_string(),
|
||||||
vals: vec![b"04ac75e0-2900-3e21-926c-2f732c26b3fc".to_vec()]
|
vals: vec![b"04ac75e0-2900-3e21-926c-2f732c26b3fc".to_vec()]
|
||||||
},
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "givenName".to_string(),
|
||||||
|
vals: vec![b"Jim".to_vec()]
|
||||||
|
},
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "jpegPhoto".to_string(),
|
atype: "jpegPhoto".to_string(),
|
||||||
vals: vec![JpegPhoto::for_tests().into_bytes()]
|
vals: vec![JpegPhoto::for_tests().into_bytes()]
|
||||||
},
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "mail".to_string(),
|
||||||
|
vals: vec![b"jim@cricket.jim".to_vec()]
|
||||||
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "objectClass".to_string(),
|
||||||
|
vals: vec![
|
||||||
|
b"inetOrgPerson".to_vec(),
|
||||||
|
b"posixAccount".to_vec(),
|
||||||
|
b"mailAccount".to_vec(),
|
||||||
|
b"person".to_vec(),
|
||||||
|
b"customUserClass".to_vec(),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "sn".to_string(),
|
||||||
|
vals: vec![b"Cricket".to_vec()]
|
||||||
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "uid".to_string(),
|
||||||
|
vals: vec![b"jim".to_vec()]
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
make_search_success(),
|
make_search_success(),
|
||||||
|
@ -1423,14 +1423,22 @@ mod tests {
|
||||||
LdapOp::SearchResultEntry(LdapSearchResultEntry {
|
LdapOp::SearchResultEntry(LdapSearchResultEntry {
|
||||||
dn: "cn=group_1,ou=groups,dc=example,dc=com".to_string(),
|
dn: "cn=group_1,ou=groups,dc=example,dc=com".to_string(),
|
||||||
attributes: vec![
|
attributes: vec![
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "objectClass".to_string(),
|
|
||||||
vals: vec![b"groupOfUniqueNames".to_vec(),]
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "cn".to_string(),
|
atype: "cn".to_string(),
|
||||||
vals: vec![b"group_1".to_vec()]
|
vals: vec![b"group_1".to_vec()]
|
||||||
},
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "entryDN".to_string(),
|
||||||
|
vals: vec![b"uid=group_1,ou=groups,dc=example,dc=com".to_vec()],
|
||||||
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "entryUuid".to_string(),
|
||||||
|
vals: vec![b"04ac75e0-2900-3e21-926c-2f732c26b3fc".to_vec()],
|
||||||
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "objectClass".to_string(),
|
||||||
|
vals: vec![b"groupOfUniqueNames".to_vec(),]
|
||||||
|
},
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "uniqueMember".to_string(),
|
atype: "uniqueMember".to_string(),
|
||||||
vals: vec![
|
vals: vec![
|
||||||
|
@ -1438,38 +1446,30 @@ mod tests {
|
||||||
b"uid=john,ou=people,dc=example,dc=com".to_vec(),
|
b"uid=john,ou=people,dc=example,dc=com".to_vec(),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "entryUuid".to_string(),
|
|
||||||
vals: vec![b"04ac75e0-2900-3e21-926c-2f732c26b3fc".to_vec()],
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "entryDN".to_string(),
|
|
||||||
vals: vec![b"uid=group_1,ou=groups,dc=example,dc=com".to_vec()],
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
LdapOp::SearchResultEntry(LdapSearchResultEntry {
|
LdapOp::SearchResultEntry(LdapSearchResultEntry {
|
||||||
dn: "cn=BestGroup,ou=groups,dc=example,dc=com".to_string(),
|
dn: "cn=BestGroup,ou=groups,dc=example,dc=com".to_string(),
|
||||||
attributes: vec![
|
attributes: vec![
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "objectClass".to_string(),
|
|
||||||
vals: vec![b"groupOfUniqueNames".to_vec(),]
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "cn".to_string(),
|
atype: "cn".to_string(),
|
||||||
vals: vec![b"BestGroup".to_vec()]
|
vals: vec![b"BestGroup".to_vec()]
|
||||||
},
|
},
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "uniqueMember".to_string(),
|
atype: "entryDN".to_string(),
|
||||||
vals: vec![b"uid=john,ou=people,dc=example,dc=com".to_vec()]
|
vals: vec![b"uid=BestGroup,ou=groups,dc=example,dc=com".to_vec()],
|
||||||
},
|
},
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "entryUuid".to_string(),
|
atype: "entryUuid".to_string(),
|
||||||
vals: vec![b"04ac75e0-2900-3e21-926c-2f732c26b3fc".to_vec()],
|
vals: vec![b"04ac75e0-2900-3e21-926c-2f732c26b3fc".to_vec()],
|
||||||
},
|
},
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "entryDN".to_string(),
|
atype: "objectClass".to_string(),
|
||||||
vals: vec![b"uid=BestGroup,ou=groups,dc=example,dc=com".to_vec()],
|
vals: vec![b"groupOfUniqueNames".to_vec(),]
|
||||||
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "uniqueMember".to_string(),
|
||||||
|
vals: vec![b"uid=john,ou=people,dc=example,dc=com".to_vec()]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
@ -2028,6 +2028,10 @@ mod tests {
|
||||||
LdapOp::SearchResultEntry(LdapSearchResultEntry {
|
LdapOp::SearchResultEntry(LdapSearchResultEntry {
|
||||||
dn: "uid=bob_1,ou=people,dc=example,dc=com".to_string(),
|
dn: "uid=bob_1,ou=people,dc=example,dc=com".to_string(),
|
||||||
attributes: vec![
|
attributes: vec![
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "cn".to_string(),
|
||||||
|
vals: vec!["Bôb Böbberson".to_string().into_bytes()]
|
||||||
|
},
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "objectClass".to_string(),
|
atype: "objectClass".to_string(),
|
||||||
vals: vec![
|
vals: vec![
|
||||||
|
@ -2036,25 +2040,21 @@ mod tests {
|
||||||
b"mailAccount".to_vec(),
|
b"mailAccount".to_vec(),
|
||||||
b"person".to_vec(),
|
b"person".to_vec(),
|
||||||
b"customUserClass".to_vec(),
|
b"customUserClass".to_vec(),
|
||||||
]
|
],
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "cn".to_string(),
|
|
||||||
vals: vec!["Bôb Böbberson".to_string().into_bytes()]
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
LdapOp::SearchResultEntry(LdapSearchResultEntry {
|
LdapOp::SearchResultEntry(LdapSearchResultEntry {
|
||||||
dn: "cn=group_1,ou=groups,dc=example,dc=com".to_string(),
|
dn: "cn=group_1,ou=groups,dc=example,dc=com".to_string(),
|
||||||
attributes: vec![
|
attributes: vec![
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "objectClass".to_string(),
|
|
||||||
vals: vec![b"groupOfUniqueNames".to_vec(),]
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "cn".to_string(),
|
atype: "cn".to_string(),
|
||||||
vals: vec![b"group_1".to_vec()]
|
vals: vec![b"group_1".to_vec()]
|
||||||
},
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "objectClass".to_string(),
|
||||||
|
vals: vec![b"groupOfUniqueNames".to_vec(),]
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
make_search_success(),
|
make_search_success(),
|
||||||
|
@ -2114,35 +2114,13 @@ mod tests {
|
||||||
dn: "uid=bob_1,ou=people,dc=example,dc=com".to_string(),
|
dn: "uid=bob_1,ou=people,dc=example,dc=com".to_string(),
|
||||||
attributes: vec![
|
attributes: vec![
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "objectclass".to_string(),
|
atype: "avatar".to_string(),
|
||||||
vals: vec![
|
vals: vec![JpegPhoto::for_tests().into_bytes()],
|
||||||
b"inetOrgPerson".to_vec(),
|
|
||||||
b"posixAccount".to_vec(),
|
|
||||||
b"mailAccount".to_vec(),
|
|
||||||
b"person".to_vec(),
|
|
||||||
b"customUserClass".to_vec(),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "uid".to_string(),
|
|
||||||
vals: vec![b"bob_1".to_vec()],
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "mail".to_string(),
|
|
||||||
vals: vec![b"bob@bobmail.bob".to_vec()],
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "sn".to_string(),
|
|
||||||
vals: vec!["Böbberson".to_string().into_bytes()],
|
|
||||||
},
|
},
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "cn".to_string(),
|
atype: "cn".to_string(),
|
||||||
vals: vec!["Bôb Böbberson".to_string().into_bytes()],
|
vals: vec!["Bôb Böbberson".to_string().into_bytes()],
|
||||||
},
|
},
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "jpegPhoto".to_string(),
|
|
||||||
vals: vec![JpegPhoto::for_tests().into_bytes()],
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "createtimestamp".to_string(),
|
atype: "createtimestamp".to_string(),
|
||||||
vals: vec![chrono::Utc
|
vals: vec![chrono::Utc
|
||||||
|
@ -2155,25 +2133,50 @@ mod tests {
|
||||||
atype: "entryuuid".to_string(),
|
atype: "entryuuid".to_string(),
|
||||||
vals: vec![b"b4ac75e0-2900-3e21-926c-2f732c26b3fc".to_vec()],
|
vals: vec![b"b4ac75e0-2900-3e21-926c-2f732c26b3fc".to_vec()],
|
||||||
},
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "jpegPhoto".to_string(),
|
||||||
|
vals: vec![JpegPhoto::for_tests().into_bytes()],
|
||||||
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "last_name".to_string(),
|
||||||
|
vals: vec!["Böbberson".to_string().into_bytes()],
|
||||||
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "mail".to_string(),
|
||||||
|
vals: vec![b"bob@bobmail.bob".to_vec()],
|
||||||
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "objectclass".to_string(),
|
||||||
|
vals: vec![
|
||||||
|
b"inetOrgPerson".to_vec(),
|
||||||
|
b"posixAccount".to_vec(),
|
||||||
|
b"mailAccount".to_vec(),
|
||||||
|
b"person".to_vec(),
|
||||||
|
b"customUserClass".to_vec(),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "sn".to_string(),
|
||||||
|
vals: vec!["Böbberson".to_string().into_bytes()],
|
||||||
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "uid".to_string(),
|
||||||
|
vals: vec![b"bob_1".to_vec()],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
// "objectclass", "dn", "uid", "cn", "member", "uniquemember"
|
// "objectclass", "dn", "uid", "cn", "member", "uniquemember"
|
||||||
LdapOp::SearchResultEntry(LdapSearchResultEntry {
|
LdapOp::SearchResultEntry(LdapSearchResultEntry {
|
||||||
dn: "cn=group_1,ou=groups,dc=example,dc=com".to_string(),
|
dn: "cn=group_1,ou=groups,dc=example,dc=com".to_string(),
|
||||||
attributes: vec![
|
attributes: vec![
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "objectclass".to_string(),
|
|
||||||
vals: vec![b"groupOfUniqueNames".to_vec()],
|
|
||||||
},
|
|
||||||
// UID
|
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "uid".to_string(),
|
|
||||||
vals: vec![b"group_1".to_vec()],
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "cn".to_string(),
|
atype: "cn".to_string(),
|
||||||
vals: vec![b"group_1".to_vec()],
|
vals: vec![b"group_1".to_vec()],
|
||||||
},
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "entryuuid".to_string(),
|
||||||
|
vals: vec![b"04ac75e0-2900-3e21-926c-2f732c26b3fc".to_vec()],
|
||||||
|
},
|
||||||
//member / uniquemember : "uid={},ou=people,{}"
|
//member / uniquemember : "uid={},ou=people,{}"
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "member".to_string(),
|
atype: "member".to_string(),
|
||||||
|
@ -2182,6 +2185,15 @@ mod tests {
|
||||||
b"uid=john,ou=people,dc=example,dc=com".to_vec(),
|
b"uid=john,ou=people,dc=example,dc=com".to_vec(),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "objectclass".to_string(),
|
||||||
|
vals: vec![b"groupOfUniqueNames".to_vec()],
|
||||||
|
},
|
||||||
|
// UID
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "uid".to_string(),
|
||||||
|
vals: vec![b"group_1".to_vec()],
|
||||||
|
},
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "uniquemember".to_string(),
|
atype: "uniquemember".to_string(),
|
||||||
vals: vec![
|
vals: vec![
|
||||||
|
@ -2189,10 +2201,6 @@ mod tests {
|
||||||
b"uid=john,ou=people,dc=example,dc=com".to_vec(),
|
b"uid=john,ou=people,dc=example,dc=com".to_vec(),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "entryuuid".to_string(),
|
|
||||||
vals: vec![b"04ac75e0-2900-3e21-926c-2f732c26b3fc".to_vec()],
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
make_search_success(),
|
make_search_success(),
|
||||||
|
@ -2924,27 +2932,27 @@ mod tests {
|
||||||
LdapOp::SearchResultEntry(LdapSearchResultEntry {
|
LdapOp::SearchResultEntry(LdapSearchResultEntry {
|
||||||
dn: "uid=test,ou=people,dc=example,dc=com".to_string(),
|
dn: "uid=test,ou=people,dc=example,dc=com".to_string(),
|
||||||
attributes: vec![
|
attributes: vec![
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "uid".to_owned(),
|
|
||||||
vals: vec![b"test".to_vec()],
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "nickname".to_owned(),
|
atype: "nickname".to_owned(),
|
||||||
vals: vec![b"Bob the Builder".to_vec()],
|
vals: vec![b"Bob the Builder".to_vec()],
|
||||||
},
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "uid".to_owned(),
|
||||||
|
vals: vec![b"test".to_vec()],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
LdapOp::SearchResultEntry(LdapSearchResultEntry {
|
LdapOp::SearchResultEntry(LdapSearchResultEntry {
|
||||||
dn: "cn=group,ou=groups,dc=example,dc=com".to_owned(),
|
dn: "cn=group,ou=groups,dc=example,dc=com".to_owned(),
|
||||||
attributes: vec![
|
attributes: vec![
|
||||||
LdapPartialAttribute {
|
|
||||||
atype: "uid".to_owned(),
|
|
||||||
vals: vec![b"group".to_vec()],
|
|
||||||
},
|
|
||||||
LdapPartialAttribute {
|
LdapPartialAttribute {
|
||||||
atype: "club_name".to_owned(),
|
atype: "club_name".to_owned(),
|
||||||
vals: vec![b"Breakfast Club".to_vec()],
|
vals: vec![b"Breakfast Club".to_vec()],
|
||||||
},
|
},
|
||||||
|
LdapPartialAttribute {
|
||||||
|
atype: "uid".to_owned(),
|
||||||
|
vals: vec![b"group".to_vec()],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
make_search_success()
|
make_search_success()
|
||||||
|
|
Loading…
Reference in a new issue