Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Ignore redactions of m.room.create events #5701

Merged
merged 2 commits into from
Jul 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/5701.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Ignore redactions of m.room.create events.
15 changes: 0 additions & 15 deletions synapse/api/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -606,21 +606,6 @@ def compute_auth_events(self, event, current_state_ids, for_verification=False):

defer.returnValue(auth_ids)

def check_redaction(self, room_version, event, auth_events):
"""Check whether the event sender is allowed to redact the target event.

Returns:
True if the the sender is allowed to redact the target event if the
target event was created by them.
False if the sender is allowed to redact the target event with no
further checks.

Raises:
AuthError if the event sender is definitely not allowed to redact
the target event.
"""
return event_auth.check_redaction(room_version, event, auth_events)

@defer.inlineCallbacks
def check_can_change_room_list(self, room_id, user):
"""Check if the user is allowed to edit the room's entry in the
Expand Down
33 changes: 24 additions & 9 deletions synapse/handlers/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from twisted.internet import defer
from twisted.internet.defer import succeed

from synapse import event_auth
from synapse.api.constants import EventTypes, Membership, RelationTypes
from synapse.api.errors import (
AuthError,
Expand Down Expand Up @@ -784,25 +785,39 @@ def is_inviter_member_event(e):
event.signatures.update(returned_invite.signatures)

if event.type == EventTypes.Redaction:
original_event = yield self.store.get_event(
event.redacts,
check_redacted=False,
get_prev_content=False,
allow_rejected=False,
allow_none=True,
check_room_id=event.room_id,
)

# we can make some additional checks now if we have the original event.
if original_event:
if original_event.type == EventTypes.Create:
raise AuthError(403, "Redacting create events is not permitted")

prev_state_ids = yield context.get_prev_state_ids(self.store)
auth_events_ids = yield self.auth.compute_auth_events(
event, prev_state_ids, for_verification=True
)
auth_events = yield self.store.get_events(auth_events_ids)
auth_events = {(e.type, e.state_key): e for e in auth_events.values()}
room_version = yield self.store.get_room_version(event.room_id)
if self.auth.check_redaction(room_version, event, auth_events=auth_events):
original_event = yield self.store.get_event(
event.redacts,
check_redacted=False,
get_prev_content=False,
allow_rejected=False,
allow_none=False,
)

if event_auth.check_redaction(room_version, event, auth_events=auth_events):
# this user doesn't have 'redact' rights, so we need to do some more
# checks on the original event. Let's start by checking the original
# event exists.
if not original_event:
raise NotFoundError("Could not find event %s" % (event.redacts,))

if event.user_id != original_event.user_id:
raise AuthError(403, "You don't have permission to redact events")

# We've already checked.
# all the checks are done.
event.internal_metadata.recheck_redaction = False

if event.type == EventTypes.Create:
Expand Down
12 changes: 12 additions & 0 deletions synapse/storage/events_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,14 @@ def get_events_as_list(
continue

original_event = original_event_entry.event
if original_event.type == EventTypes.Create:
# we never serve redactions of Creates to clients.
logger.info(
"Withholding redaction %s of create event %s",
event_id,
redacted_event_id,
)
continue

if entry.event.internal_metadata.need_to_check_redaction():
original_domain = get_domain_from_id(original_event.sender)
Expand Down Expand Up @@ -617,6 +625,10 @@ def _maybe_redact_event_row(self, original_ev, redactions):
Deferred[EventBase|None]: if the event should be redacted, a pruned
event object. Otherwise, None.
"""
if original_ev.type == "m.room.create":
# we choose to ignore redactions of m.room.create events.
return None

redaction_map = yield self._get_events_from_cache_or_db(redactions)

for redaction_id in redactions:
Expand Down
20 changes: 20 additions & 0 deletions tests/rest/client/test_redactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,23 @@ def test_redact_nonexistent_event(self):
self.assertEqual(timeline[-2]["event_id"], msg_id)
self.assertEqual(timeline[-2]["unsigned"]["redacted_by"], redaction_id)
self.assertEqual(timeline[-2]["content"], {})

def test_redact_create_event(self):
# control case: an existing event
b = self.helper.send(room_id=self.room_id, tok=self.mod_access_token)
msg_id = b["event_id"]
self._redact_event(self.mod_access_token, self.room_id, msg_id)

# sync the room, to get the id of the create event
timeline = self._sync_room_timeline(self.other_access_token, self.room_id)
create_event_id = timeline[0]["event_id"]

# room moderators cannot send redactions for create events
self._redact_event(
self.mod_access_token, self.room_id, create_event_id, expect_code=403
)

# and nor can normals
self._redact_event(
self.other_access_token, self.room_id, create_event_id, expect_code=403
)