directory.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2014-2016 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 collections import namedtuple
  16. from twisted.internet import defer
  17. from synapse.api.errors import SynapseError
  18. from synapse.storage._base import SQLBaseStore
  19. from synapse.util.caches.descriptors import cached
  20. RoomAliasMapping = namedtuple("RoomAliasMapping", ("room_id", "room_alias", "servers"))
  21. class DirectoryWorkerStore(SQLBaseStore):
  22. @defer.inlineCallbacks
  23. def get_association_from_room_alias(self, room_alias):
  24. """ Get's the room_id and server list for a given room_alias
  25. Args:
  26. room_alias (RoomAlias)
  27. Returns:
  28. Deferred: results in namedtuple with keys "room_id" and
  29. "servers" or None if no association can be found
  30. """
  31. room_id = yield self.db.simple_select_one_onecol(
  32. "room_aliases",
  33. {"room_alias": room_alias.to_string()},
  34. "room_id",
  35. allow_none=True,
  36. desc="get_association_from_room_alias",
  37. )
  38. if not room_id:
  39. return None
  40. servers = yield self.db.simple_select_onecol(
  41. "room_alias_servers",
  42. {"room_alias": room_alias.to_string()},
  43. "server",
  44. desc="get_association_from_room_alias",
  45. )
  46. if not servers:
  47. return None
  48. return RoomAliasMapping(room_id, room_alias.to_string(), servers)
  49. def get_room_alias_creator(self, room_alias):
  50. return self.db.simple_select_one_onecol(
  51. table="room_aliases",
  52. keyvalues={"room_alias": room_alias},
  53. retcol="creator",
  54. desc="get_room_alias_creator",
  55. )
  56. @cached(max_entries=5000)
  57. def get_aliases_for_room(self, room_id):
  58. return self.db.simple_select_onecol(
  59. "room_aliases",
  60. {"room_id": room_id},
  61. "room_alias",
  62. desc="get_aliases_for_room",
  63. )
  64. class DirectoryStore(DirectoryWorkerStore):
  65. @defer.inlineCallbacks
  66. def create_room_alias_association(self, room_alias, room_id, servers, creator=None):
  67. """ Creates an association between a room alias and room_id/servers
  68. Args:
  69. room_alias (RoomAlias)
  70. room_id (str)
  71. servers (list)
  72. creator (str): Optional user_id of creator.
  73. Returns:
  74. Deferred
  75. """
  76. def alias_txn(txn):
  77. self.db.simple_insert_txn(
  78. txn,
  79. "room_aliases",
  80. {
  81. "room_alias": room_alias.to_string(),
  82. "room_id": room_id,
  83. "creator": creator,
  84. },
  85. )
  86. self.db.simple_insert_many_txn(
  87. txn,
  88. table="room_alias_servers",
  89. values=[
  90. {"room_alias": room_alias.to_string(), "server": server}
  91. for server in servers
  92. ],
  93. )
  94. self._invalidate_cache_and_stream(
  95. txn, self.get_aliases_for_room, (room_id,)
  96. )
  97. try:
  98. ret = yield self.db.runInteraction(
  99. "create_room_alias_association", alias_txn
  100. )
  101. except self.database_engine.module.IntegrityError:
  102. raise SynapseError(
  103. 409, "Room alias %s already exists" % room_alias.to_string()
  104. )
  105. return ret
  106. @defer.inlineCallbacks
  107. def delete_room_alias(self, room_alias):
  108. room_id = yield self.db.runInteraction(
  109. "delete_room_alias", self._delete_room_alias_txn, room_alias
  110. )
  111. return room_id
  112. def _delete_room_alias_txn(self, txn, room_alias):
  113. txn.execute(
  114. "SELECT room_id FROM room_aliases WHERE room_alias = ?",
  115. (room_alias.to_string(),),
  116. )
  117. res = txn.fetchone()
  118. if res:
  119. room_id = res[0]
  120. else:
  121. return None
  122. txn.execute(
  123. "DELETE FROM room_aliases WHERE room_alias = ?", (room_alias.to_string(),)
  124. )
  125. txn.execute(
  126. "DELETE FROM room_alias_servers WHERE room_alias = ?",
  127. (room_alias.to_string(),),
  128. )
  129. self._invalidate_cache_and_stream(txn, self.get_aliases_for_room, (room_id,))
  130. return room_id
  131. def update_aliases_for_room(self, old_room_id, new_room_id, creator):
  132. def _update_aliases_for_room_txn(txn):
  133. sql = "UPDATE room_aliases SET room_id = ?, creator = ? WHERE room_id = ?"
  134. txn.execute(sql, (new_room_id, creator, old_room_id))
  135. self._invalidate_cache_and_stream(
  136. txn, self.get_aliases_for_room, (old_room_id,)
  137. )
  138. self._invalidate_cache_and_stream(
  139. txn, self.get_aliases_for_room, (new_room_id,)
  140. )
  141. return self.db.runInteraction(
  142. "_update_aliases_for_room_txn", _update_aliases_for_room_txn
  143. )