feat(kanidmd): add ldap support for mail primary and alternative address (#1287)

This commit is contained in:
Jan Christoph Ebersbach 2022-12-24 06:12:28 +01:00 committed by GitHub
parent 0d9467a570
commit d3e73cdac0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 90 additions and 10 deletions

View file

@ -220,6 +220,9 @@ pub const UUID_SCHEMA_CLASS_SYNC_OBJECT: Uuid = uuid!("00000000-0000-0000-0000-f
pub const UUID_SCHEMA_ATTR_SYNC_CLASS: Uuid = uuid!("00000000-0000-0000-0000-ffff00000124");
pub const UUID_SCHEMA_ATTR_SYNC_ALLOWED: Uuid = uuid!("00000000-0000-0000-0000-ffff00000125");
pub const UUID_SCHEMA_ATTR_EMAILPRIMARY: Uuid = uuid!("00000000-0000-0000-0000-ffff00000126");
pub const UUID_SCHEMA_ATTR_EMAILALTERNATIVE: Uuid = uuid!("00000000-0000-0000-0000-ffff00000127");
// System and domain infos
// I'd like to strongly criticise william of the past for making poor choices about these allocations.
pub const UUID_SYSTEM_INFO: Uuid = uuid!("00000000-0000-0000-0000-ffffff000001");

View file

@ -1795,6 +1795,24 @@ impl Entry<EntryReduced, EntryCommitted> {
atype: "entrydn".to_string(),
vals: vec![dn.as_bytes().to_vec()],
}),
"mail;primary" | "emailprimary" => {
attr_map.get(kani_a).map(|pvs| LdapPartialAttribute {
atype: ldap_a.to_string(),
vals: pvs
.first()
.map(|first| vec![first.clone()])
.unwrap_or_default(),
})
}
"mail;alternative" | "emailalternative" => {
attr_map.get(kani_a).map(|pvs| LdapPartialAttribute {
atype: ldap_a.to_string(),
vals: pvs
.split_first()
.map(|(_, rest)| rest.to_vec())
.unwrap_or_default(),
})
}
_ => attr_map.get(kani_a).map(|pvs| LdapPartialAttribute {
atype: ldap_a.to_string(),
vals: pvs.clone(),

View file

@ -526,14 +526,18 @@ fn operationerr_to_ldapresultcode(e: OperationError) -> (LdapResultCode, String)
#[inline]
pub(crate) fn ldap_all_vattrs() -> Vec<String> {
vec![
"entryuuid".to_string(),
"objectclass".to_string(),
"entrydn".to_string(),
"cn".to_string(),
"email".to_string(),
"emailaddress".to_string(),
"emailalternative".to_string(),
"emailprimary".to_string(),
"entrydn".to_string(),
"entryuuid".to_string(),
"keys".to_string(),
"mail;alternative".to_string(),
"mail;primary".to_string(),
"objectclass".to_string(),
"sshpublickey".to_string(),
"cn".to_string(),
"uidnumber".to_string(),
]
}
@ -547,13 +551,17 @@ pub(crate) fn ldap_vattr_map(input: &str) -> &str {
//
// LDAP NAME KANI ATTR SOURCE NAME
match input {
"entryuuid" => "uuid",
"objectclass" => "class",
"cn" => "name",
"email" => "mail",
"emailaddress" => "mail",
"emailalternative" => "mail",
"emailprimary" => "mail",
"entryuuid" => "uuid",
"keys" => "ssh_publickey",
"mail;alternative" => "mail",
"mail;primary" => "mail",
"objectclass" => "class",
"sshpublickey" => "ssh_publickey",
"cn" => "name",
"uidnumber" => "gidnumber",
a => a,
}
@ -912,7 +920,7 @@ mod tests {
base: "dc=example,dc=com".to_string(),
scope: LdapSearchScope::Subtree,
filter: LdapFilter::Equality("name".to_string(), "testperson1".to_string()),
attrs: vec!["name".to_string(), "mail".to_string()],
attrs: vec!["name".to_string(), "mail".to_string(), "mail;primary".to_string(), "mail;alternative".to_string(), "emailprimary".to_string(), "emailalternative".to_string()],
};
let sa_uuid = uuid::uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63930");
@ -942,6 +950,13 @@ mod tests {
"mail",
Value::EmailAddress("testperson1@example.com".to_string(), true)
),
(
"mail",
Value::EmailAddress(
"testperson1.alternative@example.com".to_string(),
false
)
),
("description", Value::new_utf8s("testperson1")),
("displayname", Value::new_utf8s("testperson1")),
("gidnumber", Value::new_uint32(12345678)),
@ -1038,7 +1053,12 @@ mod tests {
lsre,
"spn=testperson1@example.com,dc=example,dc=com",
("name", "testperson1"),
("mail", "testperson1@example.com")
("mail", "testperson1@example.com"),
("mail", "testperson1.alternative@example.com"),
("mail;primary", "testperson1@example.com"),
("mail;alternative", "testperson1.alternative@example.com"),
("emailprimary", "testperson1@example.com"),
("emailalternative", "testperson1.alternative@example.com")
);
}
_ => assert!(false),

View file

@ -1430,6 +1430,34 @@ impl<'a> SchemaWriteTransaction<'a> {
syntax: SyntaxType::EmailAddress,
},
);
self.attributes.insert(
AttrString::from("emailprimary"),
SchemaAttribute {
name: AttrString::from("emailprimary"),
uuid: UUID_SCHEMA_ATTR_EMAILPRIMARY,
description: String::from("An LDAP Compatible primary email"),
multivalue: false,
unique: false,
phantom: true,
sync_allowed: false,
index: vec![],
syntax: SyntaxType::EmailAddress,
},
);
self.attributes.insert(
AttrString::from("emailalternative"),
SchemaAttribute {
name: AttrString::from("emailalternative"),
uuid: UUID_SCHEMA_ATTR_EMAILALTERNATIVE,
description: String::from("An LDAP Compatible alternative email"),
multivalue: false,
unique: false,
phantom: true,
sync_allowed: false,
index: vec![],
syntax: SyntaxType::EmailAddress,
},
);
self.attributes.insert(
AttrString::from("emailaddress"),
SchemaAttribute {

View file

@ -319,7 +319,18 @@ impl ValueSetT for ValueSetEmailAddress {
}
fn to_proto_string_clone_iter(&self) -> Box<dyn Iterator<Item = String> + '_> {
Box::new(self.set.iter().cloned())
if self.primary.is_empty() {
Box::new(self.set.iter().cloned())
} else {
Box::new(
std::iter::once(self.primary.clone()).chain(
self.set
.iter()
.filter(|mail| **mail != self.primary)
.cloned(),
),
)
}
}
fn to_db_valueset_v2(&self) -> DbValueSetV2 {