test_redactions.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2019 The Matrix.org Foundation C.I.C.
  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 synapse.rest import admin
  16. from synapse.rest.client.v1 import login, room
  17. from synapse.rest.client.v2_alpha import sync
  18. from tests.unittest import HomeserverTestCase
  19. class RedactionsTestCase(HomeserverTestCase):
  20. """Tests that various redaction events are handled correctly"""
  21. servlets = [
  22. admin.register_servlets,
  23. room.register_servlets,
  24. login.register_servlets,
  25. sync.register_servlets,
  26. ]
  27. def make_homeserver(self, reactor, clock):
  28. config = self.default_config()
  29. config["rc_message"] = {"per_second": 0.2, "burst_count": 10}
  30. config["rc_admin_redaction"] = {"per_second": 1, "burst_count": 100}
  31. return self.setup_test_homeserver(config=config)
  32. def prepare(self, reactor, clock, hs):
  33. # register a couple of users
  34. self.mod_user_id = self.register_user("user1", "pass")
  35. self.mod_access_token = self.login("user1", "pass")
  36. self.other_user_id = self.register_user("otheruser", "pass")
  37. self.other_access_token = self.login("otheruser", "pass")
  38. # Create a room
  39. self.room_id = self.helper.create_room_as(
  40. self.mod_user_id, tok=self.mod_access_token
  41. )
  42. # Invite the other user
  43. self.helper.invite(
  44. room=self.room_id,
  45. src=self.mod_user_id,
  46. tok=self.mod_access_token,
  47. targ=self.other_user_id,
  48. )
  49. # The other user joins
  50. self.helper.join(
  51. room=self.room_id, user=self.other_user_id, tok=self.other_access_token
  52. )
  53. def _redact_event(self, access_token, room_id, event_id, expect_code=200):
  54. """Helper function to send a redaction event.
  55. Returns the json body.
  56. """
  57. path = "/_matrix/client/r0/rooms/%s/redact/%s" % (room_id, event_id)
  58. request, channel = self.make_request(
  59. "POST", path, content={}, access_token=access_token
  60. )
  61. self.render(request)
  62. self.assertEqual(int(channel.result["code"]), expect_code)
  63. return channel.json_body
  64. def _sync_room_timeline(self, access_token, room_id):
  65. request, channel = self.make_request(
  66. "GET", "sync", access_token=self.mod_access_token
  67. )
  68. self.render(request)
  69. self.assertEqual(channel.result["code"], b"200")
  70. room_sync = channel.json_body["rooms"]["join"][room_id]
  71. return room_sync["timeline"]["events"]
  72. def test_redact_event_as_moderator(self):
  73. # as a regular user, send a message to redact
  74. b = self.helper.send(room_id=self.room_id, tok=self.other_access_token)
  75. msg_id = b["event_id"]
  76. # as the moderator, send a redaction
  77. b = self._redact_event(self.mod_access_token, self.room_id, msg_id)
  78. redaction_id = b["event_id"]
  79. # now sync
  80. timeline = self._sync_room_timeline(self.mod_access_token, self.room_id)
  81. # the last event should be the redaction
  82. self.assertEqual(timeline[-1]["event_id"], redaction_id)
  83. self.assertEqual(timeline[-1]["redacts"], msg_id)
  84. # and the penultimate should be the redacted original
  85. self.assertEqual(timeline[-2]["event_id"], msg_id)
  86. self.assertEqual(timeline[-2]["unsigned"]["redacted_by"], redaction_id)
  87. self.assertEqual(timeline[-2]["content"], {})
  88. def test_redact_event_as_normal(self):
  89. # as a regular user, send a message to redact
  90. b = self.helper.send(room_id=self.room_id, tok=self.other_access_token)
  91. normal_msg_id = b["event_id"]
  92. # also send one as the admin
  93. b = self.helper.send(room_id=self.room_id, tok=self.mod_access_token)
  94. admin_msg_id = b["event_id"]
  95. # as a normal, try to redact the admin's event
  96. self._redact_event(
  97. self.other_access_token, self.room_id, admin_msg_id, expect_code=403
  98. )
  99. # now try to redact our own event
  100. b = self._redact_event(self.other_access_token, self.room_id, normal_msg_id)
  101. redaction_id = b["event_id"]
  102. # now sync
  103. timeline = self._sync_room_timeline(self.other_access_token, self.room_id)
  104. # the last event should be the redaction of the normal event
  105. self.assertEqual(timeline[-1]["event_id"], redaction_id)
  106. self.assertEqual(timeline[-1]["redacts"], normal_msg_id)
  107. # the penultimate should be the unredacted one from the admin
  108. self.assertEqual(timeline[-2]["event_id"], admin_msg_id)
  109. self.assertNotIn("redacted_by", timeline[-2]["unsigned"])
  110. self.assertTrue(timeline[-2]["content"]["body"], {})
  111. # and the antepenultimate should be the redacted normal
  112. self.assertEqual(timeline[-3]["event_id"], normal_msg_id)
  113. self.assertEqual(timeline[-3]["unsigned"]["redacted_by"], redaction_id)
  114. self.assertEqual(timeline[-3]["content"], {})
  115. def test_redact_nonexistent_event(self):
  116. # control case: an existing event
  117. b = self.helper.send(room_id=self.room_id, tok=self.other_access_token)
  118. msg_id = b["event_id"]
  119. b = self._redact_event(self.other_access_token, self.room_id, msg_id)
  120. redaction_id = b["event_id"]
  121. # room moderators can send redactions for non-existent events
  122. self._redact_event(self.mod_access_token, self.room_id, "$zzz")
  123. # ... but normals cannot
  124. self._redact_event(
  125. self.other_access_token, self.room_id, "$zzz", expect_code=404
  126. )
  127. # when we sync, we should see only the valid redaction
  128. timeline = self._sync_room_timeline(self.other_access_token, self.room_id)
  129. self.assertEqual(timeline[-1]["event_id"], redaction_id)
  130. self.assertEqual(timeline[-1]["redacts"], msg_id)
  131. # and the penultimate should be the redacted original
  132. self.assertEqual(timeline[-2]["event_id"], msg_id)
  133. self.assertEqual(timeline[-2]["unsigned"]["redacted_by"], redaction_id)
  134. self.assertEqual(timeline[-2]["content"], {})
  135. def test_redact_create_event(self):
  136. # control case: an existing event
  137. b = self.helper.send(room_id=self.room_id, tok=self.mod_access_token)
  138. msg_id = b["event_id"]
  139. self._redact_event(self.mod_access_token, self.room_id, msg_id)
  140. # sync the room, to get the id of the create event
  141. timeline = self._sync_room_timeline(self.other_access_token, self.room_id)
  142. create_event_id = timeline[0]["event_id"]
  143. # room moderators cannot send redactions for create events
  144. self._redact_event(
  145. self.mod_access_token, self.room_id, create_event_id, expect_code=403
  146. )
  147. # and nor can normals
  148. self._redact_event(
  149. self.other_access_token, self.room_id, create_event_id, expect_code=403
  150. )
  151. def test_redact_event_as_moderator_ratelimit(self):
  152. """Tests that the correct ratelimiting is applied to redactions
  153. """
  154. message_ids = []
  155. # as a regular user, send messages to redact
  156. for _ in range(20):
  157. b = self.helper.send(room_id=self.room_id, tok=self.other_access_token)
  158. message_ids.append(b["event_id"])
  159. self.reactor.advance(10) # To get around ratelimits
  160. # as the moderator, send a bunch of redactions
  161. for msg_id in message_ids:
  162. # These should all succeed, even though this would be denied by
  163. # the standard message ratelimiter
  164. self._redact_event(self.mod_access_token, self.room_id, msg_id)