test_redactions.py 7.8 KB

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