directory.py 5.6 KB

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