mirror of
https://mau.dev/maunium/synapse.git
synced 2024-12-16 06:43:51 +01:00
Implement rechecking of redactions
This commit is contained in:
parent
7a3ec5b022
commit
7709d2bd16
5 changed files with 53 additions and 10 deletions
|
@ -627,7 +627,7 @@ class Auth(object):
|
|||
|
||||
defer.returnValue(auth_ids)
|
||||
|
||||
def check_redaction(self, event, auth_events):
|
||||
def check_redaction(self, room_version, event, auth_events):
|
||||
"""Check whether the event sender is allowed to redact the target event.
|
||||
|
||||
Returns:
|
||||
|
@ -640,7 +640,7 @@ class Auth(object):
|
|||
AuthError if the event sender is definitely not allowed to redact
|
||||
the target event.
|
||||
"""
|
||||
return event_auth.check_redaction(event, auth_events)
|
||||
return event_auth.check_redaction(room_version, event, auth_events)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def check_can_change_room_list(self, room_id, user):
|
||||
|
|
|
@ -20,7 +20,13 @@ from signedjson.key import decode_verify_key_bytes
|
|||
from signedjson.sign import SignatureVerifyException, verify_signed_json
|
||||
from unpaddedbase64 import decode_base64
|
||||
|
||||
from synapse.api.constants import KNOWN_ROOM_VERSIONS, EventTypes, JoinRules, Membership
|
||||
from synapse.api.constants import (
|
||||
KNOWN_ROOM_VERSIONS,
|
||||
EventTypes,
|
||||
JoinRules,
|
||||
Membership,
|
||||
RoomVersions,
|
||||
)
|
||||
from synapse.api.errors import AuthError, EventSizeError, SynapseError
|
||||
from synapse.types import UserID, get_domain_from_id
|
||||
|
||||
|
@ -168,7 +174,7 @@ def check(room_version, event, auth_events, do_sig_check=True, do_size_check=Tru
|
|||
_check_power_levels(event, auth_events)
|
||||
|
||||
if event.type == EventTypes.Redaction:
|
||||
check_redaction(event, auth_events)
|
||||
check_redaction(room_version, event, auth_events)
|
||||
|
||||
logger.debug("Allowing! %s", event)
|
||||
|
||||
|
@ -422,7 +428,7 @@ def _can_send_event(event, auth_events):
|
|||
return True
|
||||
|
||||
|
||||
def check_redaction(event, auth_events):
|
||||
def check_redaction(room_version, event, auth_events):
|
||||
"""Check whether the event sender is allowed to redact the target event.
|
||||
|
||||
Returns:
|
||||
|
@ -442,10 +448,16 @@ def check_redaction(event, auth_events):
|
|||
if user_level >= redact_level:
|
||||
return False
|
||||
|
||||
redacter_domain = get_domain_from_id(event.event_id)
|
||||
redactee_domain = get_domain_from_id(event.redacts)
|
||||
if redacter_domain == redactee_domain:
|
||||
if room_version in (RoomVersions.V1, RoomVersions.V2, RoomVersions.VDH_TEST):
|
||||
redacter_domain = get_domain_from_id(event.event_id)
|
||||
redactee_domain = get_domain_from_id(event.redacts)
|
||||
if redacter_domain == redactee_domain:
|
||||
return True
|
||||
elif room_version == RoomVersions.V3:
|
||||
event.internal_metadata.recheck_redaction = True
|
||||
return True
|
||||
else:
|
||||
raise RuntimeError("Unrecognized room version %r" % (room_version,))
|
||||
|
||||
raise AuthError(
|
||||
403,
|
||||
|
|
|
@ -63,6 +63,9 @@ class _EventInternalMetadata(object):
|
|||
"""
|
||||
return getattr(self, "send_on_behalf_of", None)
|
||||
|
||||
def need_to_check_redaction(self):
|
||||
return getattr(self, "recheck_redaction", False)
|
||||
|
||||
|
||||
def _event_dict_property(key):
|
||||
# We want to be able to use hasattr with the event dict properties.
|
||||
|
|
|
@ -767,7 +767,8 @@ class EventCreationHandler(object):
|
|||
auth_events = {
|
||||
(e.type, e.state_key): e for e in auth_events.values()
|
||||
}
|
||||
if self.auth.check_redaction(event, auth_events=auth_events):
|
||||
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,
|
||||
|
@ -781,6 +782,9 @@ class EventCreationHandler(object):
|
|||
"You don't have permission to redact events"
|
||||
)
|
||||
|
||||
# We've already checked.
|
||||
event.internal_metadata.recheck_redaction = False
|
||||
|
||||
if event.type == EventTypes.Create:
|
||||
prev_state_ids = yield context.get_prev_state_ids(self.store)
|
||||
if prev_state_ids:
|
||||
|
|
|
@ -21,13 +21,14 @@ from canonicaljson import json
|
|||
|
||||
from twisted.internet import defer
|
||||
|
||||
from synapse.api.constants import EventFormatVersions
|
||||
from synapse.api.constants import EventFormatVersions, EventTypes
|
||||
from synapse.api.errors import NotFoundError
|
||||
from synapse.events import FrozenEvent, event_type_from_format_version # noqa: F401
|
||||
# these are only included to make the type annotations work
|
||||
from synapse.events.snapshot import EventContext # noqa: F401
|
||||
from synapse.events.utils import prune_event
|
||||
from synapse.metrics.background_process_metrics import run_as_background_process
|
||||
from synapse.types import get_domain_from_id
|
||||
from synapse.util.logcontext import (
|
||||
LoggingContext,
|
||||
PreserveLoggingContext,
|
||||
|
@ -174,6 +175,29 @@ class EventsWorkerStore(SQLBaseStore):
|
|||
if not entry:
|
||||
continue
|
||||
|
||||
# Some redactions in room version v3 need to be rechecked if we
|
||||
# didn't have the redacted event at the time, so we recheck on read
|
||||
# instead.
|
||||
if not allow_rejected and entry.event.type == EventTypes.Redaction:
|
||||
if entry.event.internal_metadata.need_to_check_redaction():
|
||||
orig = yield self.get_event(
|
||||
entry.event.redacts,
|
||||
allow_none=True,
|
||||
allow_rejected=True,
|
||||
get_prev_content=False,
|
||||
)
|
||||
expected_domain = get_domain_from_id(entry.event.sender)
|
||||
if orig and get_domain_from_id(orig.sender) == expected_domain:
|
||||
# This redaction event is allowed. Mark as not needing a
|
||||
# recheck.
|
||||
entry.event.recheck_redaction = False
|
||||
else:
|
||||
# We don't have the event that is being redacted, so we
|
||||
# assume that the event isn't authorized for now. (If we
|
||||
# later receive the event, then we will always redact
|
||||
# it anyway, since we have this redaction)
|
||||
continue
|
||||
|
||||
if allow_rejected or not entry.event.rejected_reason:
|
||||
if check_redacted and entry.redacted_event:
|
||||
event = entry.redacted_event
|
||||
|
|
Loading…
Reference in a new issue