test_redactions.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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 prepare(self, reactor, clock, hs):
  28. # register a couple of users
  29. self.mod_user_id = self.register_user("user1", "pass")
  30. self.mod_access_token = self.login("user1", "pass")
  31. self.other_user_id = self.register_user("otheruser", "pass")
  32. self.other_access_token = self.login("otheruser", "pass")
  33. # Create a room
  34. self.room_id = self.helper.create_room_as(
  35. self.mod_user_id, tok=self.mod_access_token
  36. )
  37. # Invite the other user
  38. self.helper.invite(
  39. room=self.room_id,
  40. src=self.mod_user_id,
  41. tok=self.mod_access_token,
  42. targ=self.other_user_id,
  43. )
  44. # The other user joins
  45. self.helper.join(
  46. room=self.room_id, user=self.other_user_id, tok=self.other_access_token
  47. )
  48. def _redact_event(self, access_token, room_id, event_id, expect_code=200):
  49. """Helper function to send a redaction event.
  50. Returns the json body.
  51. """
  52. path = "/_matrix/client/r0/rooms/%s/redact/%s" % (room_id, event_id)
  53. request, channel = self.make_request(
  54. "POST", path, content={}, access_token=access_token
  55. )
  56. self.render(request)
  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. request, channel = self.make_request(
  61. "GET", "sync", access_token=self.mod_access_token
  62. )
  63. self.render(request)
  64. self.assertEqual(channel.result["code"], b"200")
  65. room_sync = channel.json_body["rooms"]["join"][room_id]
  66. return room_sync["timeline"]["events"]
  67. def test_redact_event_as_moderator(self):
  68. # as a regular user, send a message to redact
  69. b = self.helper.send(room_id=self.room_id, tok=self.other_access_token)
  70. msg_id = b["event_id"]
  71. # as the moderator, send a redaction
  72. b = self._redact_event(self.mod_access_token, self.room_id, msg_id)
  73. redaction_id = b["event_id"]
  74. # now sync
  75. timeline = self._sync_room_timeline(self.mod_access_token, self.room_id)
  76. # the last event should be the redaction
  77. self.assertEqual(timeline[-1]["event_id"], redaction_id)
  78. self.assertEqual(timeline[-1]["redacts"], msg_id)
  79. # and the penultimate should be the redacted original
  80. self.assertEqual(timeline[-2]["event_id"], msg_id)
  81. self.assertEqual(timeline[-2]["unsigned"]["redacted_by"], redaction_id)
  82. self.assertEqual(timeline[-2]["content"], {})
  83. def test_redact_event_as_normal(self):
  84. # as a regular user, send a message to redact
  85. b = self.helper.send(room_id=self.room_id, tok=self.other_access_token)
  86. normal_msg_id = b["event_id"]
  87. # also send one as the admin
  88. b = self.helper.send(room_id=self.room_id, tok=self.mod_access_token)
  89. admin_msg_id = b["event_id"]
  90. # as a normal, try to redact the admin's event
  91. self._redact_event(
  92. self.other_access_token, self.room_id, admin_msg_id, expect_code=403
  93. )
  94. # now try to redact our own event
  95. b = self._redact_event(self.other_access_token, self.room_id, normal_msg_id)
  96. redaction_id = b["event_id"]
  97. # now sync
  98. timeline = self._sync_room_timeline(self.other_access_token, self.room_id)
  99. # the last event should be the redaction of the normal event
  100. self.assertEqual(timeline[-1]["event_id"], redaction_id)
  101. self.assertEqual(timeline[-1]["redacts"], normal_msg_id)
  102. # the penultimate should be the unredacted one from the admin
  103. self.assertEqual(timeline[-2]["event_id"], admin_msg_id)
  104. self.assertNotIn("redacted_by", timeline[-2]["unsigned"])
  105. self.assertTrue(timeline[-2]["content"]["body"], {})
  106. # and the antepenultimate should be the redacted normal
  107. self.assertEqual(timeline[-3]["event_id"], normal_msg_id)
  108. self.assertEqual(timeline[-3]["unsigned"]["redacted_by"], redaction_id)
  109. self.assertEqual(timeline[-3]["content"], {})
  110. def test_redact_nonexistent_event(self):
  111. # control case: an existing event
  112. b = self.helper.send(room_id=self.room_id, tok=self.other_access_token)
  113. msg_id = b["event_id"]
  114. b = self._redact_event(self.other_access_token, self.room_id, msg_id)
  115. redaction_id = b["event_id"]
  116. # room moderators can send redactions for non-existent events
  117. self._redact_event(self.mod_access_token, self.room_id, "$zzz")
  118. # ... but normals cannot
  119. self._redact_event(
  120. self.other_access_token, self.room_id, "$zzz", expect_code=404
  121. )
  122. # when we sync, we should see only the valid redaction
  123. timeline = self._sync_room_timeline(self.other_access_token, self.room_id)
  124. self.assertEqual(timeline[-1]["event_id"], redaction_id)
  125. self.assertEqual(timeline[-1]["redacts"], msg_id)
  126. # and the penultimate should be the redacted original
  127. self.assertEqual(timeline[-2]["event_id"], msg_id)
  128. self.assertEqual(timeline[-2]["unsigned"]["redacted_by"], redaction_id)
  129. self.assertEqual(timeline[-2]["content"], {})
  130. def test_redact_create_event(self):
  131. # control case: an existing event
  132. b = self.helper.send(room_id=self.room_id, tok=self.mod_access_token)
  133. msg_id = b["event_id"]
  134. self._redact_event(self.mod_access_token, self.room_id, msg_id)
  135. # sync the room, to get the id of the create event
  136. timeline = self._sync_room_timeline(self.other_access_token, self.room_id)
  137. create_event_id = timeline[0]["event_id"]
  138. # room moderators cannot send redactions for create events
  139. self._redact_event(
  140. self.mod_access_token, self.room_id, create_event_id, expect_code=403
  141. )
  142. # and nor can normals
  143. self._redact_event(
  144. self.other_access_token, self.room_id, create_event_id, expect_code=403
  145. )