lookupservlet.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2014,2017 OpenMarket Ltd
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. from twisted.web.resource import Resource
  16. from sydent.db.threepid_associations import GlobalAssociationStore
  17. import logging
  18. import json
  19. import signedjson.sign
  20. from sydent.http.servlets import get_args, jsonwrap, send_cors
  21. logger = logging.getLogger(__name__)
  22. class LookupServlet(Resource):
  23. isLeaf = True
  24. def __init__(self, syd):
  25. self.sydent = syd
  26. def render_GET(self, request):
  27. """
  28. Look up an individual threepid.
  29. Params: 'medium': the medium of the threepid
  30. 'address': the address of the threepid
  31. Returns: A signed association if the threepid has a corresponding mxid, otherwise the empty object.
  32. """
  33. send_cors(request)
  34. err, args = get_args(request, ('medium', 'address'))
  35. if err:
  36. return json.dumps(err)
  37. medium = args['medium']
  38. address = args['address']
  39. globalAssocStore = GlobalAssociationStore(self.sydent)
  40. sgassoc = globalAssocStore.signedAssociationStringForThreepid(medium, address)
  41. if not sgassoc:
  42. return json.dumps({})
  43. sgassoc = json.loads(sgassoc.encode('utf8'))
  44. if not self.sydent.server_name in sgassoc['signatures']:
  45. # We have not yet worked out what the proper trust model should be.
  46. #
  47. # Maybe clients implicitly trust a server they talk to (and so we
  48. # should sign every assoc we return as ourselves, so they can
  49. # verify this).
  50. #
  51. # Maybe clients really want to know what server did the original
  52. # verification, and want to only know exactly who signed the assoc.
  53. #
  54. # Until we work out what we should do, sign all assocs we return as
  55. # ourself. This is vaguely ok because there actually is only one
  56. # identity server, but it happens to have two names (matrix.org and
  57. # vector.im), and so we're not really lying too much.
  58. #
  59. # We do this when we return assocs, not when we receive them over
  60. # replication, so that we can undo this decision in the future if
  61. # we wish, without having destroyed the raw underlying data.
  62. sgassoc = signedjson.sign.sign_json(
  63. sgassoc,
  64. self.sydent.server_name,
  65. self.sydent.keyring.ed25519
  66. )
  67. return json.dumps(sgassoc)
  68. def render_POST(self, request):
  69. """
  70. Bulk-lookup for threepids.
  71. ** DEPRECATED **
  72. Use /bulk_lookup which returns the result encapsulated in a dict
  73. Params: 'threepids': list of threepids, each of which is a list of medium, address
  74. Returns: List of results where each result is a 3 item list of medium, address, mxid
  75. Threepids for which no mapping is found are omitted.
  76. """
  77. send_cors(request)
  78. err, args = get_args(request, ('threepids',))
  79. if err:
  80. return json.dumps(err)
  81. threepids = args['threepids']
  82. if not isinstance(threepids, list):
  83. request.setResponseCode(400)
  84. return {'errcode': 'M_INVALID_PARAM', 'error': 'threepids must be a list'}, None
  85. logger.info("Bulk lookup of %d threepids (deprecated endpoint)", len(threepids))
  86. globalAssocStore = GlobalAssociationStore(self.sydent)
  87. results = globalAssocStore.getMxids(threepids)
  88. return json.dumps(results)
  89. @jsonwrap
  90. def render_OPTIONS(self, request):
  91. send_cors(request)
  92. request.setResponseCode(200)
  93. return {}