From 53d7114352be06ecafbcabd767d74011a820b2fe Mon Sep 17 00:00:00 2001 From: Maxime Dor Date: Fri, 27 Jan 2017 01:47:08 +0100 Subject: [PATCH] Refactor lookup providers - Create lookup strategy object to handle several provider - New root ID server provider - Refactor code into appropriate classes --- .../io/kamax/mxisd/api/ThreePidType.groovy | 7 +++ .../controller/v1/MappingController.groovy | 54 ++++-------------- .../io/kamax/mxisd/lookup/LdapProvider.groovy | 56 +++++++++++++++++++ .../kamax/mxisd/lookup/LookupStrategy.groovy | 9 +++ .../lookup/PriorityLookupStrategy.groovy | 38 +++++++++++++ .../io/kamax/mxisd/lookup/RootProvider.groovy | 34 +++++++++++ .../mxisd/lookup/ThreePidProvider.groovy | 14 +++++ 7 files changed, 170 insertions(+), 42 deletions(-) create mode 100644 src/main/groovy/io/kamax/mxisd/api/ThreePidType.groovy create mode 100644 src/main/groovy/io/kamax/mxisd/lookup/LdapProvider.groovy create mode 100644 src/main/groovy/io/kamax/mxisd/lookup/LookupStrategy.groovy create mode 100644 src/main/groovy/io/kamax/mxisd/lookup/PriorityLookupStrategy.groovy create mode 100644 src/main/groovy/io/kamax/mxisd/lookup/RootProvider.groovy create mode 100644 src/main/groovy/io/kamax/mxisd/lookup/ThreePidProvider.groovy diff --git a/src/main/groovy/io/kamax/mxisd/api/ThreePidType.groovy b/src/main/groovy/io/kamax/mxisd/api/ThreePidType.groovy new file mode 100644 index 0000000..c2fe224 --- /dev/null +++ b/src/main/groovy/io/kamax/mxisd/api/ThreePidType.groovy @@ -0,0 +1,7 @@ +package io.kamax.mxisd.api + +enum ThreePidType { + + email + +} diff --git a/src/main/groovy/io/kamax/mxisd/controller/v1/MappingController.groovy b/src/main/groovy/io/kamax/mxisd/controller/v1/MappingController.groovy index 25f0bea..7c27519 100644 --- a/src/main/groovy/io/kamax/mxisd/controller/v1/MappingController.groovy +++ b/src/main/groovy/io/kamax/mxisd/controller/v1/MappingController.groovy @@ -21,14 +21,9 @@ package io.kamax.mxisd.controller.v1 import groovy.json.JsonOutput -import io.kamax.mxisd.config.LdapConfig -import io.kamax.mxisd.exception.BadRequestException +import io.kamax.mxisd.api.ThreePidType +import io.kamax.mxisd.lookup.LookupStrategy import io.kamax.mxisd.signature.SignatureManager -import org.apache.directory.api.ldap.model.cursor.EntryCursor -import org.apache.directory.api.ldap.model.entry.Attribute -import org.apache.directory.api.ldap.model.message.SearchScope -import org.apache.directory.ldap.client.api.LdapConnection -import org.apache.directory.ldap.client.api.LdapNetworkConnection import org.springframework.beans.factory.annotation.Autowired import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestParam @@ -40,50 +35,25 @@ import static org.springframework.web.bind.annotation.RequestMethod.GET class MappingController { @Autowired - private LdapConfig ldapCfg + private LookupStrategy strategy @Autowired private SignatureManager signMgr @RequestMapping(value = "/_matrix/identity/api/v1/lookup", method = GET) String lookup(@RequestParam String medium, @RequestParam String address) { - if (!"email".contentEquals(medium)) { - throw new BadRequestException("Invalid medium type") + ThreePidType type = ThreePidType.valueOf(medium) + Optional lookupOpt = strategy.find(type, address) + if (!lookupOpt.isPresent()) { + return JsonOutput.toJson([]) } - LdapConnection conn = new LdapNetworkConnection(ldapCfg.getHost(), ldapCfg.getPort()) - try { - conn.bind(ldapCfg.getBindDn(), ldapCfg.getBindPassword()) - - String searchQuery = ldapCfg.getQuery().replaceAll("%3pid", address) - EntryCursor cursor = conn.search(ldapCfg.getBaseDn(), searchQuery, SearchScope.SUBTREE, ldapCfg.getAttribute()) - try { - if (!cursor.next()) { - return JsonOutput.toJson([]) - } - - Attribute attribute = cursor.get().get(ldapCfg.getAttribute()) - if (attribute == null) { - return JsonOutput.toJson([]) - } - - def data = new LinkedHashMap([ - address : address, - medium : medium, - mxid : attribute.get().toString(), - not_before: 0, - not_after : 9223372036854775807, - ts : 0 - ]) - - data['signatures'] = signMgr.signMessage(JsonOutput.toJson(data)) - return JsonOutput.toJson(data) - } finally { - cursor.close() - } - } finally { - conn.close() + def lookup = lookupOpt.get() + if (lookup['signatures'] == null) { + lookup['signatures'] = signMgr.signMessage(JsonOutput.toJson(lookup)) } + + return JsonOutput.toJson(lookup) } } diff --git a/src/main/groovy/io/kamax/mxisd/lookup/LdapProvider.groovy b/src/main/groovy/io/kamax/mxisd/lookup/LdapProvider.groovy new file mode 100644 index 0000000..4d3fb0c --- /dev/null +++ b/src/main/groovy/io/kamax/mxisd/lookup/LdapProvider.groovy @@ -0,0 +1,56 @@ +package io.kamax.mxisd.lookup + +import io.kamax.mxisd.api.ThreePidType +import io.kamax.mxisd.config.LdapConfig +import org.apache.directory.api.ldap.model.cursor.EntryCursor +import org.apache.directory.api.ldap.model.entry.Attribute +import org.apache.directory.api.ldap.model.message.SearchScope +import org.apache.directory.ldap.client.api.LdapConnection +import org.apache.directory.ldap.client.api.LdapNetworkConnection +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Component + +@Component +class LdapProvider implements ThreePidProvider { + + @Autowired + private LdapConfig ldapCfg + + @Override + int getPriority() { + return 20 + } + + @Override + Optional find(ThreePidType type, String threePid) { + LdapConnection conn = new LdapNetworkConnection(ldapCfg.getHost(), ldapCfg.getPort()) + try { + conn.bind(ldapCfg.getBindDn(), ldapCfg.getBindPassword()) + + String searchQuery = ldapCfg.getQuery().replaceAll("%3pid", threePid) + EntryCursor cursor = conn.search(ldapCfg.getBaseDn(), searchQuery, SearchScope.SUBTREE, ldapCfg.getAttribute()) + try { + if (cursor.next()) { + Attribute attribute = cursor.get().get(ldapCfg.getAttribute()) + if (attribute != null) { + return Optional.of([ + address : threePid, + medium : type, + mxid : attribute.get().toString(), + not_before: 0, + not_after : 9223372036854775807, + ts : 0 + ]) + } + } + } finally { + cursor.close() + } + } finally { + conn.close() + } + + return Optional.empty() + } + +} diff --git a/src/main/groovy/io/kamax/mxisd/lookup/LookupStrategy.groovy b/src/main/groovy/io/kamax/mxisd/lookup/LookupStrategy.groovy new file mode 100644 index 0000000..46aaa68 --- /dev/null +++ b/src/main/groovy/io/kamax/mxisd/lookup/LookupStrategy.groovy @@ -0,0 +1,9 @@ +package io.kamax.mxisd.lookup + +import io.kamax.mxisd.api.ThreePidType + +interface LookupStrategy { + + Optional find(ThreePidType type, String threePid) + +} diff --git a/src/main/groovy/io/kamax/mxisd/lookup/PriorityLookupStrategy.groovy b/src/main/groovy/io/kamax/mxisd/lookup/PriorityLookupStrategy.groovy new file mode 100644 index 0000000..31423f4 --- /dev/null +++ b/src/main/groovy/io/kamax/mxisd/lookup/PriorityLookupStrategy.groovy @@ -0,0 +1,38 @@ +package io.kamax.mxisd.lookup + +import io.kamax.mxisd.api.ThreePidType +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Component + +@Component +class PriorityLookupStrategy implements LookupStrategy { + + @Autowired + private List providers + + @Override + Optional find(ThreePidType type, String threePid) { + if (ThreePidType.email != type) { + throw new IllegalArgumentException("${type} is currently not supported") + } + + providers.sort(new Comparator() { + + @Override + int compare(ThreePidProvider o1, ThreePidProvider o2) { + return Integer.compare(o2.getPriority(), o1.getPriority()) + } + + }) + + for (ThreePidProvider provider : providers) { + Optional lookupDataOpt = provider.find(type, threePid) + if (lookupDataOpt.isPresent()) { + return lookupDataOpt + } + } + + return Optional.empty() + } + +} diff --git a/src/main/groovy/io/kamax/mxisd/lookup/RootProvider.groovy b/src/main/groovy/io/kamax/mxisd/lookup/RootProvider.groovy new file mode 100644 index 0000000..79c14ec --- /dev/null +++ b/src/main/groovy/io/kamax/mxisd/lookup/RootProvider.groovy @@ -0,0 +1,34 @@ +package io.kamax.mxisd.lookup + +import groovy.json.JsonSlurper +import io.kamax.mxisd.api.ThreePidType +import org.springframework.stereotype.Component + +@Component +class RootProvider implements ThreePidProvider { + + private List roots = Arrays.asList("https://matrix.org", "https://vector.im") + private JsonSlurper json = new JsonSlurper() + + @Override + int getPriority() { + return 0 + } + + @Override + Optional find(ThreePidType type, String threePid) { + for (String root : roots) { + HttpURLConnection rootSrvConn = (HttpURLConnection) new URL( + "${root}/_matrix/identity/api/v1/lookup?medium=${type}&address=${threePid}" + ).openConnection() + + def output = json.parseText(rootSrvConn.getInputStream().getText()) + if (output['address'] != null) { + return Optional.of(output) + } + } + + return Optional.empty() + } + +} diff --git a/src/main/groovy/io/kamax/mxisd/lookup/ThreePidProvider.groovy b/src/main/groovy/io/kamax/mxisd/lookup/ThreePidProvider.groovy new file mode 100644 index 0000000..67ac8d2 --- /dev/null +++ b/src/main/groovy/io/kamax/mxisd/lookup/ThreePidProvider.groovy @@ -0,0 +1,14 @@ +package io.kamax.mxisd.lookup + +import io.kamax.mxisd.api.ThreePidType + +interface ThreePidProvider { + + /** + * Higher has more priority + */ + int getPriority() // Should not be here but let's KISS for now + + Optional find(ThreePidType type, String threePid) + +}