diff options
author | Paul Evans <leonerd@leonerd.org.uk> | 2016-08-18 20:52:50 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-08-18 20:52:50 +0100 |
commit | 5674ea3e6c51b26c828fc8a78bc82832d72c50d4 (patch) | |
tree | 26f0e424dbe3ec3a1ecb5074ed32b8e55c9abbaa /synapse/appservice/api.py | |
parent | Merge pull request #1027 from matrix-org/erikj/appservice_stream (diff) | |
parent | Move validation logic for AS 3PE query response into ApplicationServiceApi cl... (diff) | |
download | synapse-5674ea3e6c51b26c828fc8a78bc82832d72c50d4.tar.xz |
Merge pull request #1026 from matrix-org/paul/thirdpartylookup
3rd party entity lookup
Diffstat (limited to 'synapse/appservice/api.py')
-rw-r--r-- | synapse/appservice/api.py | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/synapse/appservice/api.py b/synapse/appservice/api.py index 6da6a1b62e..066127b666 100644 --- a/synapse/appservice/api.py +++ b/synapse/appservice/api.py @@ -17,6 +17,7 @@ from twisted.internet import defer from synapse.api.errors import CodeMessageException from synapse.http.client import SimpleHttpClient from synapse.events.utils import serialize_event +from synapse.types import ThirdPartyEntityKind import logging import urllib @@ -24,6 +25,28 @@ import urllib logger = logging.getLogger(__name__) +def _is_valid_3pe_result(r, field): + if not isinstance(r, dict): + return False + + for k in (field, "protocol"): + if k not in r: + return False + if not isinstance(r[k], str): + return False + + if "fields" not in r: + return False + fields = r["fields"] + if not isinstance(fields, dict): + return False + for k in fields.keys(): + if not isinstance(fields[k], str): + return False + + return True + + class ApplicationServiceApi(SimpleHttpClient): """This class manages HS -> AS communications, including querying and pushing. @@ -72,6 +95,43 @@ class ApplicationServiceApi(SimpleHttpClient): defer.returnValue(False) @defer.inlineCallbacks + def query_3pe(self, service, kind, protocol, fields): + if kind == ThirdPartyEntityKind.USER: + uri = "%s/3pu/%s" % (service.url, urllib.quote(protocol)) + required_field = "userid" + elif kind == ThirdPartyEntityKind.LOCATION: + uri = "%s/3pl/%s" % (service.url, urllib.quote(protocol)) + required_field = "alias" + else: + raise ValueError( + "Unrecognised 'kind' argument %r to query_3pe()", kind + ) + + try: + response = yield self.get_json(uri, fields) + if not isinstance(response, list): + logger.warning( + "query_3pe to %s returned an invalid response %r", + uri, response + ) + defer.returnValue([]) + + ret = [] + for r in response: + if _is_valid_3pe_result(r, field=required_field): + ret.append(r) + else: + logger.warning( + "query_3pe to %s returned an invalid result %r", + uri, r + ) + + defer.returnValue(ret) + except Exception as ex: + logger.warning("query_3pe to %s threw exception %s", uri, ex) + defer.returnValue([]) + + @defer.inlineCallbacks def push_bulk(self, service, events, txn_id=None): events = self._serialize(events) |