test_shadow_banned.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. # Copyright 2020 The Matrix.org Foundation C.I.C.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. from unittest.mock import Mock, patch
  15. import synapse.rest.admin
  16. from synapse.api.constants import EventTypes
  17. from synapse.rest.client import (
  18. directory,
  19. login,
  20. profile,
  21. room,
  22. room_upgrade_rest_servlet,
  23. )
  24. from synapse.types import UserID
  25. from tests import unittest
  26. class _ShadowBannedBase(unittest.HomeserverTestCase):
  27. def prepare(self, reactor, clock, homeserver):
  28. # Create two users, one of which is shadow-banned.
  29. self.banned_user_id = self.register_user("banned", "test")
  30. self.banned_access_token = self.login("banned", "test")
  31. self.store = self.hs.get_datastore()
  32. self.get_success(
  33. self.store.set_shadow_banned(UserID.from_string(self.banned_user_id), True)
  34. )
  35. self.other_user_id = self.register_user("otheruser", "pass")
  36. self.other_access_token = self.login("otheruser", "pass")
  37. # To avoid the tests timing out don't add a delay to "annoy the requester".
  38. @patch("random.randint", new=lambda a, b: 0)
  39. class RoomTestCase(_ShadowBannedBase):
  40. servlets = [
  41. synapse.rest.admin.register_servlets_for_client_rest_resource,
  42. directory.register_servlets,
  43. login.register_servlets,
  44. room.register_servlets,
  45. room_upgrade_rest_servlet.register_servlets,
  46. ]
  47. def test_invite(self):
  48. """Invites from shadow-banned users don't actually get sent."""
  49. # The create works fine.
  50. room_id = self.helper.create_room_as(
  51. self.banned_user_id, tok=self.banned_access_token
  52. )
  53. # Inviting the user completes successfully.
  54. self.helper.invite(
  55. room=room_id,
  56. src=self.banned_user_id,
  57. tok=self.banned_access_token,
  58. targ=self.other_user_id,
  59. )
  60. # But the user wasn't actually invited.
  61. invited_rooms = self.get_success(
  62. self.store.get_invited_rooms_for_local_user(self.other_user_id)
  63. )
  64. self.assertEqual(invited_rooms, [])
  65. def test_invite_3pid(self):
  66. """Ensure that a 3PID invite does not attempt to contact the identity server."""
  67. identity_handler = self.hs.get_identity_handler()
  68. identity_handler.lookup_3pid = Mock(
  69. side_effect=AssertionError("This should not get called")
  70. )
  71. # The create works fine.
  72. room_id = self.helper.create_room_as(
  73. self.banned_user_id, tok=self.banned_access_token
  74. )
  75. # Inviting the user completes successfully.
  76. channel = self.make_request(
  77. "POST",
  78. "/rooms/%s/invite" % (room_id,),
  79. {"id_server": "test", "medium": "email", "address": "test@test.test"},
  80. access_token=self.banned_access_token,
  81. )
  82. self.assertEquals(200, channel.code, channel.result)
  83. # This should have raised an error earlier, but double check this wasn't called.
  84. identity_handler.lookup_3pid.assert_not_called()
  85. def test_create_room(self):
  86. """Invitations during a room creation should be discarded, but the room still gets created."""
  87. # The room creation is successful.
  88. channel = self.make_request(
  89. "POST",
  90. "/_matrix/client/r0/createRoom",
  91. {"visibility": "public", "invite": [self.other_user_id]},
  92. access_token=self.banned_access_token,
  93. )
  94. self.assertEquals(200, channel.code, channel.result)
  95. room_id = channel.json_body["room_id"]
  96. # But the user wasn't actually invited.
  97. invited_rooms = self.get_success(
  98. self.store.get_invited_rooms_for_local_user(self.other_user_id)
  99. )
  100. self.assertEqual(invited_rooms, [])
  101. # Since a real room was created, the other user should be able to join it.
  102. self.helper.join(room_id, self.other_user_id, tok=self.other_access_token)
  103. # Both users should be in the room.
  104. users = self.get_success(self.store.get_users_in_room(room_id))
  105. self.assertCountEqual(users, ["@banned:test", "@otheruser:test"])
  106. def test_message(self):
  107. """Messages from shadow-banned users don't actually get sent."""
  108. room_id = self.helper.create_room_as(
  109. self.other_user_id, tok=self.other_access_token
  110. )
  111. # The user should be in the room.
  112. self.helper.join(room_id, self.banned_user_id, tok=self.banned_access_token)
  113. # Sending a message should complete successfully.
  114. result = self.helper.send_event(
  115. room_id=room_id,
  116. type=EventTypes.Message,
  117. content={"msgtype": "m.text", "body": "with right label"},
  118. tok=self.banned_access_token,
  119. )
  120. self.assertIn("event_id", result)
  121. event_id = result["event_id"]
  122. latest_events = self.get_success(
  123. self.store.get_latest_event_ids_in_room(room_id)
  124. )
  125. self.assertNotIn(event_id, latest_events)
  126. def test_upgrade(self):
  127. """A room upgrade should fail, but look like it succeeded."""
  128. # The create works fine.
  129. room_id = self.helper.create_room_as(
  130. self.banned_user_id, tok=self.banned_access_token
  131. )
  132. channel = self.make_request(
  133. "POST",
  134. "/_matrix/client/r0/rooms/%s/upgrade" % (room_id,),
  135. {"new_version": "6"},
  136. access_token=self.banned_access_token,
  137. )
  138. self.assertEquals(200, channel.code, channel.result)
  139. # A new room_id should be returned.
  140. self.assertIn("replacement_room", channel.json_body)
  141. new_room_id = channel.json_body["replacement_room"]
  142. # It doesn't really matter what API we use here, we just want to assert
  143. # that the room doesn't exist.
  144. summary = self.get_success(self.store.get_room_summary(new_room_id))
  145. # The summary should be empty since the room doesn't exist.
  146. self.assertEqual(summary, {})
  147. def test_typing(self):
  148. """Typing notifications should not be propagated into the room."""
  149. # The create works fine.
  150. room_id = self.helper.create_room_as(
  151. self.banned_user_id, tok=self.banned_access_token
  152. )
  153. channel = self.make_request(
  154. "PUT",
  155. "/rooms/%s/typing/%s" % (room_id, self.banned_user_id),
  156. {"typing": True, "timeout": 30000},
  157. access_token=self.banned_access_token,
  158. )
  159. self.assertEquals(200, channel.code)
  160. # There should be no typing events.
  161. event_source = self.hs.get_event_sources().sources.typing
  162. self.assertEquals(event_source.get_current_key(), 0)
  163. # The other user can join and send typing events.
  164. self.helper.join(room_id, self.other_user_id, tok=self.other_access_token)
  165. channel = self.make_request(
  166. "PUT",
  167. "/rooms/%s/typing/%s" % (room_id, self.other_user_id),
  168. {"typing": True, "timeout": 30000},
  169. access_token=self.other_access_token,
  170. )
  171. self.assertEquals(200, channel.code)
  172. # These appear in the room.
  173. self.assertEquals(event_source.get_current_key(), 1)
  174. events = self.get_success(
  175. event_source.get_new_events(
  176. user=UserID.from_string(self.other_user_id),
  177. from_key=0,
  178. limit=None,
  179. room_ids=[room_id],
  180. is_guest=False,
  181. )
  182. )
  183. self.assertEquals(
  184. events[0],
  185. [
  186. {
  187. "type": "m.typing",
  188. "room_id": room_id,
  189. "content": {"user_ids": [self.other_user_id]},
  190. }
  191. ],
  192. )
  193. # To avoid the tests timing out don't add a delay to "annoy the requester".
  194. @patch("random.randint", new=lambda a, b: 0)
  195. class ProfileTestCase(_ShadowBannedBase):
  196. servlets = [
  197. synapse.rest.admin.register_servlets_for_client_rest_resource,
  198. login.register_servlets,
  199. profile.register_servlets,
  200. room.register_servlets,
  201. ]
  202. def test_displayname(self):
  203. """Profile changes should succeed, but don't end up in a room."""
  204. original_display_name = "banned"
  205. new_display_name = "new name"
  206. # Join a room.
  207. room_id = self.helper.create_room_as(
  208. self.banned_user_id, tok=self.banned_access_token
  209. )
  210. # The update should succeed.
  211. channel = self.make_request(
  212. "PUT",
  213. "/_matrix/client/r0/profile/%s/displayname" % (self.banned_user_id,),
  214. {"displayname": new_display_name},
  215. access_token=self.banned_access_token,
  216. )
  217. self.assertEquals(200, channel.code, channel.result)
  218. self.assertEqual(channel.json_body, {})
  219. # The user's display name should be updated.
  220. channel = self.make_request(
  221. "GET", "/profile/%s/displayname" % (self.banned_user_id,)
  222. )
  223. self.assertEqual(channel.code, 200, channel.result)
  224. self.assertEqual(channel.json_body["displayname"], new_display_name)
  225. # But the display name in the room should not be.
  226. message_handler = self.hs.get_message_handler()
  227. event = self.get_success(
  228. message_handler.get_room_data(
  229. self.banned_user_id,
  230. room_id,
  231. "m.room.member",
  232. self.banned_user_id,
  233. )
  234. )
  235. self.assertEqual(
  236. event.content, {"membership": "join", "displayname": original_display_name}
  237. )
  238. def test_room_displayname(self):
  239. """Changes to state events for a room should be processed, but not end up in the room."""
  240. original_display_name = "banned"
  241. new_display_name = "new name"
  242. # Join a room.
  243. room_id = self.helper.create_room_as(
  244. self.banned_user_id, tok=self.banned_access_token
  245. )
  246. # The update should succeed.
  247. channel = self.make_request(
  248. "PUT",
  249. "/_matrix/client/r0/rooms/%s/state/m.room.member/%s"
  250. % (room_id, self.banned_user_id),
  251. {"membership": "join", "displayname": new_display_name},
  252. access_token=self.banned_access_token,
  253. )
  254. self.assertEquals(200, channel.code, channel.result)
  255. self.assertIn("event_id", channel.json_body)
  256. # The display name in the room should not be changed.
  257. message_handler = self.hs.get_message_handler()
  258. event = self.get_success(
  259. message_handler.get_room_data(
  260. self.banned_user_id,
  261. room_id,
  262. "m.room.member",
  263. self.banned_user_id,
  264. )
  265. )
  266. self.assertEqual(
  267. event.content, {"membership": "join", "displayname": original_display_name}
  268. )