diff --git a/build.gradle b/build.gradle index 3bb0429..04eb442 100644 --- a/build.gradle +++ b/build.gradle @@ -108,7 +108,7 @@ dependencies { compile 'net.i2p.crypto:eddsa:0.3.0' // LDAP connector - compile 'org.apache.directory.api:api-all:1.0.0' + compile 'org.apache.directory.api:api-all:1.0.3' // DNS lookups compile 'dnsjava:dnsjava:2.1.9' diff --git a/docs/stores/ldap.md b/docs/stores/ldap.md index 535f2fc..3c86f4b 100644 --- a/docs/stores/ldap.md +++ b/docs/stores/ldap.md @@ -89,7 +89,7 @@ ldap: #### 3PIDs You can also change the attribute lists for 3PID, like email or phone numbers. -The following example would overwrite the [default list of attributes](../../src/main/java/io/kamax/ma1sd/config/ldap/LdapConfig.java#L64) +The following example would overwrite the [default list of attributes](../../src/main/java/io/kamax/mxisd/config/ldap/LdapConfig.java#L64) for emails and phone number: ```yaml ldap: diff --git a/src/main/java/io/kamax/mxisd/backend/ldap/LdapThreePidProvider.java b/src/main/java/io/kamax/mxisd/backend/ldap/LdapThreePidProvider.java index c868f53..45049b7 100644 --- a/src/main/java/io/kamax/mxisd/backend/ldap/LdapThreePidProvider.java +++ b/src/main/java/io/kamax/mxisd/backend/ldap/LdapThreePidProvider.java @@ -41,7 +41,10 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.Optional; +import java.util.stream.Collectors; public class LdapThreePidProvider extends LdapBackend implements IThreePidProvider { @@ -137,4 +140,61 @@ public class LdapThreePidProvider extends LdapBackend implements IThreePidProvid return mappingsFound; } + private List getAttributes() { + final List attributes = getCfg().getAttribute().getThreepid().values().stream().flatMap(List::stream) + .collect(Collectors.toList()); + attributes.add(getUidAtt()); + return attributes; + } + + private Optional getAttributeValue(Entry entry, List attributes) { + return attributes.stream() + .map(attr -> getAttribute(entry, attr)) + .filter(Objects::nonNull) + .filter(Optional::isPresent) + .map(Optional::get) + .findFirst(); + } + + @Override + public Iterable populateHashes() { + List result = new ArrayList<>(); + String filter = getCfg().getIdentity().getFilter(); + + try (LdapConnection conn = getConn()) { + bind(conn); + + log.debug("Query: {}", filter); + List attributes = getAttributes(); + log.debug("Attributes: {}", GsonUtil.build().toJson(attributes)); + + for (String baseDN : getBaseDNs()) { + log.debug("Base DN: {}", baseDN); + + try (EntryCursor cursor = conn.search(baseDN, filter, SearchScope.SUBTREE, attributes.toArray(new String[0]))) { + while (cursor.next()) { + Entry entry = cursor.get(); + log.info("Found possible match, DN: {}", entry.getDn().getName()); + Optional mxid = getAttribute(entry, getUidAtt()); + if (!mxid.isPresent()) { + continue; + } + + for (Map.Entry> attributeEntry : getCfg().getAttribute().getThreepid().entrySet()) { + String medium = attributeEntry.getKey(); + getAttributeValue(entry, attributeEntry.getValue()) + .ifPresent(s -> result.add(new ThreePidMapping(medium, s, buildMatrixIdFromUid(mxid.get())))); + } + } + } catch (CursorLdapReferralException e) { + log.warn("3PID is only available via referral, skipping", e); + } catch (IOException | LdapException | CursorException e) { + log.error("Unable to fetch 3PID mappings", e); + } + } + } catch (LdapException | IOException e) { + log.error("Unable to fetch 3PID mappings", e); + } + return result; + } } diff --git a/src/main/java/io/kamax/mxisd/backend/sql/SqlThreePidProvider.java b/src/main/java/io/kamax/mxisd/backend/sql/SqlThreePidProvider.java index c70a042..c4fa2dc 100644 --- a/src/main/java/io/kamax/mxisd/backend/sql/SqlThreePidProvider.java +++ b/src/main/java/io/kamax/mxisd/backend/sql/SqlThreePidProvider.java @@ -107,14 +107,16 @@ public abstract class SqlThreePidProvider implements IThreePidProvider { @Override public Iterable populateHashes() { - if (StringUtils.isBlank(cfg.getLookup().getQuery())) { + String query = cfg.getLookup().getQuery(); + if (StringUtils.isBlank(query)) { log.warn("Lookup query not configured, skip."); return Collections.emptyList(); } + log.debug("Uses query to match users: {}", query); List result = new ArrayList<>(); try (Connection connection = pool.get()) { - PreparedStatement statement = connection.prepareStatement(cfg.getLookup().getQuery()); + PreparedStatement statement = connection.prepareStatement(query); try (ResultSet resultSet = statement.executeQuery()) { while (resultSet.next()) { String mxid = resultSet.getString("mxid"); diff --git a/src/main/java/io/kamax/mxisd/hash/HashEngine.java b/src/main/java/io/kamax/mxisd/hash/HashEngine.java index e026c94..3721512 100644 --- a/src/main/java/io/kamax/mxisd/hash/HashEngine.java +++ b/src/main/java/io/kamax/mxisd/hash/HashEngine.java @@ -35,7 +35,9 @@ public class HashEngine { hashStorage.clear(); for (IThreePidProvider provider : providers) { try { + LOGGER.info("Populate hashes from the handler: {}", provider.getClass().getCanonicalName()); for (ThreePidMapping pidMapping : provider.populateHashes()) { + LOGGER.debug("Found 3PID: {}", pidMapping); hashStorage.add(pidMapping, hash(pidMapping)); } } catch (Exception e) { diff --git a/src/main/java/io/kamax/mxisd/http/undertow/handler/identity/v2/HashLookupHandler.java b/src/main/java/io/kamax/mxisd/http/undertow/handler/identity/v2/HashLookupHandler.java index 2b21c84..bc2c5c7 100644 --- a/src/main/java/io/kamax/mxisd/http/undertow/handler/identity/v2/HashLookupHandler.java +++ b/src/main/java/io/kamax/mxisd/http/undertow/handler/identity/v2/HashLookupHandler.java @@ -85,6 +85,7 @@ public class HashLookupHandler extends LookupHandler implements ApiHandler { default: throw new InvalidParamException(); } + hashManager.getRotationStrategy().newRequest(); } private void noneAlgorithm(HttpServerExchange exchange, HashLookupRequest request, ClientHashLookupRequest input) throws Exception { diff --git a/src/main/java/io/kamax/mxisd/lookup/strategy/LookupStrategy.java b/src/main/java/io/kamax/mxisd/lookup/strategy/LookupStrategy.java index 5e31f08..76683a6 100644 --- a/src/main/java/io/kamax/mxisd/lookup/strategy/LookupStrategy.java +++ b/src/main/java/io/kamax/mxisd/lookup/strategy/LookupStrategy.java @@ -46,6 +46,4 @@ public interface LookupStrategy { Optional findRecursive(SingleLookupRequest request); CompletableFuture> find(BulkLookupRequest requests); - - CompletableFuture> find(HashLookupRequest request); } diff --git a/src/main/java/io/kamax/mxisd/lookup/strategy/RecursivePriorityLookupStrategy.java b/src/main/java/io/kamax/mxisd/lookup/strategy/RecursivePriorityLookupStrategy.java index 39fa89d..4804034 100644 --- a/src/main/java/io/kamax/mxisd/lookup/strategy/RecursivePriorityLookupStrategy.java +++ b/src/main/java/io/kamax/mxisd/lookup/strategy/RecursivePriorityLookupStrategy.java @@ -26,17 +26,23 @@ import io.kamax.matrix.json.MatrixJson; import io.kamax.mxisd.config.MxisdConfig; import io.kamax.mxisd.exception.ConfigurationException; import io.kamax.mxisd.hash.HashManager; -import io.kamax.mxisd.hash.storage.HashStorage; -import io.kamax.mxisd.lookup.*; +import io.kamax.mxisd.lookup.ALookupRequest; +import io.kamax.mxisd.lookup.BulkLookupRequest; +import io.kamax.mxisd.lookup.SingleLookupReply; +import io.kamax.mxisd.lookup.SingleLookupRequest; +import io.kamax.mxisd.lookup.ThreePidMapping; import io.kamax.mxisd.lookup.fetcher.IBridgeFetcher; import io.kamax.mxisd.lookup.provider.IThreePidProvider; import org.apache.commons.codec.digest.DigestUtils; -import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.UnknownHostException; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -238,13 +244,4 @@ public class RecursivePriorityLookupStrategy implements LookupStrategy { result.complete(mapFoundAll); return bulkLookupInProgress.remove(payloadId); } - - @Override - public CompletableFuture> find(HashLookupRequest request) { - HashStorage hashStorage = hashManager.getHashStorage(); - CompletableFuture> result = new CompletableFuture<>(); - result.complete(hashStorage.find(request.getHashes()).stream().map(Pair::getValue).collect(Collectors.toList())); - hashManager.getRotationStrategy().newRequest(); - return result; - } }