diff --git a/application.example.yaml b/application.example.yaml index 605a490..2b9373b 100644 --- a/application.example.yaml +++ b/application.example.yaml @@ -61,7 +61,6 @@ ldap: bindDn: 'CN=Matrix Identity Server,CN=Users,DC=example,DC=org' bindPassword: 'password' baseDn: 'CN=Users,DC=example,DC=org' - query: '(|(mailPrimaryAddress=%3pid)(mail=%3pid)(otherMailbox=%3pid))' # How should we resolve the Matrix ID in case of a match using the attribute. # @@ -81,6 +80,17 @@ ldap: # are typically not used. attribute: 'sAMAccountName' + # Configure each 3PID type with a dedicated query. + mappings: + email: "(|(mailPrimaryAddress=%3pid)(mail=%3pid)(otherMailbox=%3pid))" + + # Phone numbers query. + # + # Phone numbers use the MSISDN format: https://en.wikipedia.org/wiki/MSISDN + # This format does not include international prefix (+ or 00) and therefore has to be put in the query. + # Adapt this to your needs for each attribute. + msisdn: "(|(telephoneNumber=+%3pid)(mobile=+%3pid)(homePhone=+%3pid)(otherMobile=+3pid)(otherHomePhone=+%3pid)(otherTelephone=+%3pid))" + forward: diff --git a/src/main/groovy/io/kamax/mxisd/api/ThreePidType.groovy b/src/main/groovy/io/kamax/mxisd/api/ThreePidType.groovy index 5618547..29ef36d 100644 --- a/src/main/groovy/io/kamax/mxisd/api/ThreePidType.groovy +++ b/src/main/groovy/io/kamax/mxisd/api/ThreePidType.groovy @@ -22,6 +22,7 @@ package io.kamax.mxisd.api enum ThreePidType { - email + email, + msisdn, } diff --git a/src/main/groovy/io/kamax/mxisd/config/LdapConfig.groovy b/src/main/groovy/io/kamax/mxisd/config/LdapConfig.groovy index e9710d8..f9f2882 100644 --- a/src/main/groovy/io/kamax/mxisd/config/LdapConfig.groovy +++ b/src/main/groovy/io/kamax/mxisd/config/LdapConfig.groovy @@ -20,21 +20,27 @@ package io.kamax.mxisd.config +import io.kamax.mxisd.api.ThreePidType +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.InitializingBean import org.springframework.boot.context.properties.ConfigurationProperties import org.springframework.context.annotation.Configuration @Configuration @ConfigurationProperties(prefix = "ldap") -class LdapConfig { +class LdapConfig implements InitializingBean { + + private Logger log = LoggerFactory.getLogger(LdapConfig.class) private String host private int port private String baseDn - private String query private String type private String attribute private String bindDn private String bindPassword + private Map mappings String getHost() { return host @@ -60,14 +66,6 @@ class LdapConfig { this.baseDn = baseDn } - String getQuery() { - return query - } - - void setQuery(String query) { - this.query = query - } - String getType() { return type } @@ -100,4 +98,24 @@ class LdapConfig { this.bindPassword = bindPassword } + Map getMappings() { + return mappings + } + + void setMappings(Map mappings) { + this.mappings = mappings + } + + Optional getMapping(ThreePidType type) { + if (mappings == null) { + return Optional.empty() + } + + return Optional.ofNullable(mappings.get(type)) + } + + @Override + void afterPropertiesSet() throws Exception { + log.info("Matrix ID type: {}", getType()) + } } diff --git a/src/main/groovy/io/kamax/mxisd/lookup/provider/LdapProvider.groovy b/src/main/groovy/io/kamax/mxisd/lookup/provider/LdapProvider.groovy index af124c3..9cb8e23 100644 --- a/src/main/groovy/io/kamax/mxisd/lookup/provider/LdapProvider.groovy +++ b/src/main/groovy/io/kamax/mxisd/lookup/provider/LdapProvider.groovy @@ -31,12 +31,11 @@ import org.apache.directory.ldap.client.api.LdapConnection import org.apache.directory.ldap.client.api.LdapNetworkConnection import org.slf4j.Logger import org.slf4j.LoggerFactory -import org.springframework.beans.factory.InitializingBean import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Component @Component -class LdapProvider implements ThreePidProvider, InitializingBean { +class LdapProvider implements ThreePidProvider { public static final String UID = "uid" public static final String MATRIX_ID = "mxid" @@ -49,13 +48,6 @@ class LdapProvider implements ThreePidProvider, InitializingBean { @Autowired private LdapConfig ldapCfg - @Override - void afterPropertiesSet() throws Exception { - if (!Arrays.asList(UID, MATRIX_ID).contains(ldapCfg.getType())) { - throw new IllegalArgumentException(ldapCfg.getType() + " is not a valid LDAP lookup type") - } - } - @Override boolean isLocal() { return true @@ -74,7 +66,13 @@ class LdapProvider implements ThreePidProvider, InitializingBean { try { conn.bind(ldapCfg.getBindDn(), ldapCfg.getBindPassword()) - String searchQuery = ldapCfg.getQuery().replaceAll("%3pid", request.getThreePid()) + Optional queryOpt = ldapCfg.getMapping(request.getType()) + if (!queryOpt.isPresent()) { + log.warn("{} is not a supported 3PID type for LDAP lookup", request.getType()) + return Optional.empty() + } + + String searchQuery = queryOpt.get().replaceAll("%3pid", request.getThreePid()) EntryCursor cursor = conn.search(ldapCfg.getBaseDn(), searchQuery, SearchScope.SUBTREE, ldapCfg.getAttribute()) try { if (cursor.next()) { @@ -90,16 +88,14 @@ class LdapProvider implements ThreePidProvider, InitializingBean { // TODO Should we turn this block into a map of functions? if (StringUtils.equals(UID, ldapCfg.getType())) { matrixId.append("@").append(data).append(":").append(srvCfg.getName()) - } - if (StringUtils.equals(MATRIX_ID, ldapCfg.getType())) { + } else if (StringUtils.equals(MATRIX_ID, ldapCfg.getType())) { matrixId.append(data) - } - - if (matrixId.length() < 1) { + } else { log.warn("Bind was found but type ${ldapCfg.getType()} is not supported") return Optional.empty() } + log.info("Found a match in LDAP") return Optional.of([ address : request.getThreePid(), medium : request.getType(), @@ -121,5 +117,4 @@ class LdapProvider implements ThreePidProvider, InitializingBean { return Optional.empty() } - }