package teams.provision; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ldap.core.AttributesMapper; import org.springframework.ldap.core.LdapOperations; import org.springframework.ldap.filter.AndFilter; import org.springframework.ldap.filter.EqualsFilter; import org.springframework.ldap.support.LdapEncoder; import teams.domain.Person; import javax.naming.NamingException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttribute; import javax.naming.directory.BasicAttributes; import java.time.Instant; import java.time.format.DateTimeFormatter; import java.util.List; import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; public class LdapUserDetailsManager implements UserDetailsManager { private static final Logger LOG = LoggerFactory.getLogger(LdapUserDetailsManager.class); private final LdapOperations ldapOperations; private final Pattern RFC_822 = Pattern.compile("^(.{12})(\\d{2})(.*)$"); public LdapUserDetailsManager(LdapOperations ldapOperations) { this.ldapOperations = ldapOperations; } private <T> List<T> persons(String urn, AttributesMapper<T> attributesMapper) { AndFilter filter = new AndFilter() .and(new EqualsFilter("objectclass", "collabPerson")) .and(new EqualsFilter("collabpersonid", urn)); String encode = filter.encode(); LOG.info("LDAP query {}", encode); //we have provided the ldapOperations with a base so here we need an empty String List<T> results = ldapOperations.search("", encode, attributesMapper); LOG.info("LDAP query result {}", results); return results; } @Override public Optional<teams.migration.Person> findPersonById(String urn) { List<teams.migration.Person> persons = persons(urn, attributes -> { String mail = this.safeGetAttribute(attributes, "mail"); String cn = this.safeGetAttribute(attributes, "cn"); String isGuest = this.safeGetAttribute(attributes, "collabpersonisguest"); String collabpersonregistered = this.safeGetAttribute(attributes, "collabpersonregistered"); Instant created = (collabpersonregistered != null ? //RFC-1123 updates RFC-822 changing the year from two digits to four Instant.from(DateTimeFormatter.RFC_1123_DATE_TIME.parse(rfc822ToRFC1123(collabpersonregistered))) : Instant.now()); return new teams.migration.Person(urn, cn, mail, "TRUE".equals(isGuest), created); }); return persons.stream().findFirst(); } private String rfc822ToRFC1123(String date) { Matcher matcher = RFC_822.matcher(date); matcher.find(); int twoDigitYear = Integer.parseInt(matcher.group(2)); String year = String.valueOf(twoDigitYear + (twoDigitYear < 67 ? 2000 : 1900)); return matcher.replaceFirst(String.format("$1%s$3", year)); } private String safeGetAttribute(Attributes attributes, String name) throws NamingException { Attribute attribute = attributes.get(name); return attribute == null ? null : (String) attribute.get(); } }