Ignore redactions of m.room.create events (#5701)
parent
1def298119
commit
9c70a02a9c
|
@ -0,0 +1 @@
|
||||||
|
Ignore redactions of m.room.create events.
|
|
@ -606,21 +606,6 @@ class Auth(object):
|
||||||
|
|
||||||
defer.returnValue(auth_ids)
|
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
|
@defer.inlineCallbacks
|
||||||
def check_can_change_room_list(self, room_id, user):
|
def check_can_change_room_list(self, room_id, user):
|
||||||
"""Check if the user is allowed to edit the room's entry in the
|
"""Check if the user is allowed to edit the room's entry in the
|
||||||
|
|
|
@ -23,6 +23,7 @@ from canonicaljson import encode_canonical_json, json
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
from twisted.internet.defer import succeed
|
from twisted.internet.defer import succeed
|
||||||
|
|
||||||
|
from synapse import event_auth
|
||||||
from synapse.api.constants import EventTypes, Membership, RelationTypes
|
from synapse.api.constants import EventTypes, Membership, RelationTypes
|
||||||
from synapse.api.errors import (
|
from synapse.api.errors import (
|
||||||
AuthError,
|
AuthError,
|
||||||
|
@ -784,6 +785,20 @@ class EventCreationHandler(object):
|
||||||
event.signatures.update(returned_invite.signatures)
|
event.signatures.update(returned_invite.signatures)
|
||||||
|
|
||||||
if event.type == EventTypes.Redaction:
|
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)
|
prev_state_ids = yield context.get_prev_state_ids(self.store)
|
||||||
auth_events_ids = yield self.auth.compute_auth_events(
|
auth_events_ids = yield self.auth.compute_auth_events(
|
||||||
event, prev_state_ids, for_verification=True
|
event, prev_state_ids, for_verification=True
|
||||||
|
@ -791,18 +806,18 @@ class EventCreationHandler(object):
|
||||||
auth_events = yield self.store.get_events(auth_events_ids)
|
auth_events = yield self.store.get_events(auth_events_ids)
|
||||||
auth_events = {(e.type, e.state_key): e for e in auth_events.values()}
|
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)
|
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(
|
if event_auth.check_redaction(room_version, event, auth_events=auth_events):
|
||||||
event.redacts,
|
# this user doesn't have 'redact' rights, so we need to do some more
|
||||||
check_redacted=False,
|
# checks on the original event. Let's start by checking the original
|
||||||
get_prev_content=False,
|
# event exists.
|
||||||
allow_rejected=False,
|
if not original_event:
|
||||||
allow_none=False,
|
raise NotFoundError("Could not find event %s" % (event.redacts,))
|
||||||
)
|
|
||||||
if event.user_id != original_event.user_id:
|
if event.user_id != original_event.user_id:
|
||||||
raise AuthError(403, "You don't have permission to redact events")
|
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
|
event.internal_metadata.recheck_redaction = False
|
||||||
|
|
||||||
if event.type == EventTypes.Create:
|
if event.type == EventTypes.Create:
|
||||||
|
|
|
@ -259,6 +259,14 @@ class EventsWorkerStore(SQLBaseStore):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
original_event = original_event_entry.event
|
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():
|
if entry.event.internal_metadata.need_to_check_redaction():
|
||||||
original_domain = get_domain_from_id(original_event.sender)
|
original_domain = get_domain_from_id(original_event.sender)
|
||||||
|
@ -617,6 +625,10 @@ class EventsWorkerStore(SQLBaseStore):
|
||||||
Deferred[EventBase|None]: if the event should be redacted, a pruned
|
Deferred[EventBase|None]: if the event should be redacted, a pruned
|
||||||
event object. Otherwise, None.
|
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)
|
redaction_map = yield self._get_events_from_cache_or_db(redactions)
|
||||||
|
|
||||||
for redaction_id in redactions:
|
for redaction_id in redactions:
|
||||||
|
|
|
@ -157,3 +157,23 @@ class RedactionsTestCase(HomeserverTestCase):
|
||||||
self.assertEqual(timeline[-2]["event_id"], msg_id)
|
self.assertEqual(timeline[-2]["event_id"], msg_id)
|
||||||
self.assertEqual(timeline[-2]["unsigned"]["redacted_by"], redaction_id)
|
self.assertEqual(timeline[-2]["unsigned"]["redacted_by"], redaction_id)
|
||||||
self.assertEqual(timeline[-2]["content"], {})
|
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
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue