mirror of
https://mau.dev/maunium/synapse.git
synced 2024-12-15 00:53:52 +01:00
Store rejected remote invite events as outliers
Currently they're stored as non-outliers even though the server isn't in the room, which can be problematic in places where the code assumes it has the state for all non outlier events. In particular, there is an edge case where persisting the leave event triggers a state resolution, which requires looking up the room version from state. Since the server doesn't have the state, this causes an exception to be thrown.
This commit is contained in:
parent
6b90ae6efc
commit
886e5acc76
3 changed files with 21 additions and 38 deletions
|
@ -32,7 +32,6 @@ from synapse.api.errors import (
|
||||||
HttpResponseException,
|
HttpResponseException,
|
||||||
SynapseError,
|
SynapseError,
|
||||||
)
|
)
|
||||||
from synapse.events import builder
|
|
||||||
from synapse.federation.federation_base import FederationBase, event_from_pdu_json
|
from synapse.federation.federation_base import FederationBase, event_from_pdu_json
|
||||||
from synapse.util import logcontext, unwrapFirstError
|
from synapse.util import logcontext, unwrapFirstError
|
||||||
from synapse.util.caches.expiringcache import ExpiringCache
|
from synapse.util.caches.expiringcache import ExpiringCache
|
||||||
|
@ -66,6 +65,8 @@ class FederationClient(FederationBase):
|
||||||
self.state = hs.get_state_handler()
|
self.state = hs.get_state_handler()
|
||||||
self.transport_layer = hs.get_federation_transport_client()
|
self.transport_layer = hs.get_federation_transport_client()
|
||||||
|
|
||||||
|
self.event_builder_factory = hs.get_event_builder_factory()
|
||||||
|
|
||||||
self._get_pdu_cache = ExpiringCache(
|
self._get_pdu_cache = ExpiringCache(
|
||||||
cache_name="get_pdu_cache",
|
cache_name="get_pdu_cache",
|
||||||
clock=self._clock,
|
clock=self._clock,
|
||||||
|
@ -571,7 +572,12 @@ class FederationClient(FederationBase):
|
||||||
if "prev_state" not in pdu_dict:
|
if "prev_state" not in pdu_dict:
|
||||||
pdu_dict["prev_state"] = []
|
pdu_dict["prev_state"] = []
|
||||||
|
|
||||||
ev = builder.EventBuilder(pdu_dict)
|
# Strip off the fields that we want to clobber.
|
||||||
|
pdu_dict.pop("origin", None)
|
||||||
|
pdu_dict.pop("origin_server_ts", None)
|
||||||
|
pdu_dict.pop("unsigned", None)
|
||||||
|
|
||||||
|
ev = self.event_builder_factory.new(pdu_dict)
|
||||||
|
|
||||||
defer.returnValue(
|
defer.returnValue(
|
||||||
(destination, ev)
|
(destination, ev)
|
||||||
|
|
|
@ -43,10 +43,7 @@ from synapse.api.errors import (
|
||||||
StoreError,
|
StoreError,
|
||||||
SynapseError,
|
SynapseError,
|
||||||
)
|
)
|
||||||
from synapse.crypto.event_signing import (
|
from synapse.crypto.event_signing import compute_event_signature
|
||||||
add_hashes_and_signatures,
|
|
||||||
compute_event_signature,
|
|
||||||
)
|
|
||||||
from synapse.events.validator import EventValidator
|
from synapse.events.validator import EventValidator
|
||||||
from synapse.replication.http.federation import (
|
from synapse.replication.http.federation import (
|
||||||
ReplicationCleanRoomRestServlet,
|
ReplicationCleanRoomRestServlet,
|
||||||
|
@ -58,7 +55,6 @@ from synapse.types import UserID, get_domain_from_id
|
||||||
from synapse.util import logcontext, unwrapFirstError
|
from synapse.util import logcontext, unwrapFirstError
|
||||||
from synapse.util.async_helpers import Linearizer
|
from synapse.util.async_helpers import Linearizer
|
||||||
from synapse.util.distributor import user_joined_room
|
from synapse.util.distributor import user_joined_room
|
||||||
from synapse.util.frozenutils import unfreeze
|
|
||||||
from synapse.util.logutils import log_function
|
from synapse.util.logutils import log_function
|
||||||
from synapse.util.retryutils import NotRetryingDestination
|
from synapse.util.retryutils import NotRetryingDestination
|
||||||
from synapse.visibility import filter_events_for_server
|
from synapse.visibility import filter_events_for_server
|
||||||
|
@ -1083,7 +1079,9 @@ class FederationHandler(BaseHandler):
|
||||||
handled_events = set()
|
handled_events = set()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
event = self._sign_event(event)
|
self._sign_event(event)
|
||||||
|
event.internal_metadata.outlier = False
|
||||||
|
|
||||||
# Try the host we successfully got a response to /make_join/
|
# Try the host we successfully got a response to /make_join/
|
||||||
# request first.
|
# request first.
|
||||||
try:
|
try:
|
||||||
|
@ -1289,13 +1287,7 @@ class FederationHandler(BaseHandler):
|
||||||
event.internal_metadata.outlier = True
|
event.internal_metadata.outlier = True
|
||||||
event.internal_metadata.invite_from_remote = True
|
event.internal_metadata.invite_from_remote = True
|
||||||
|
|
||||||
event.signatures.update(
|
self._sign_event(event)
|
||||||
compute_event_signature(
|
|
||||||
event,
|
|
||||||
self.hs.hostname,
|
|
||||||
self.hs.config.signing_key[0]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
context = yield self.state_handler.compute_event_context(event)
|
context = yield self.state_handler.compute_event_context(event)
|
||||||
yield self.persist_events_and_notify([(event, context)])
|
yield self.persist_events_and_notify([(event, context)])
|
||||||
|
@ -1313,7 +1305,7 @@ class FederationHandler(BaseHandler):
|
||||||
# Mark as outlier as we don't have any state for this event; we're not
|
# Mark as outlier as we don't have any state for this event; we're not
|
||||||
# even in the room.
|
# even in the room.
|
||||||
event.internal_metadata.outlier = True
|
event.internal_metadata.outlier = True
|
||||||
event = self._sign_event(event)
|
self._sign_event(event)
|
||||||
|
|
||||||
# Try the host that we succesfully called /make_leave/ on first for
|
# Try the host that we succesfully called /make_leave/ on first for
|
||||||
# the /send_leave/ request.
|
# the /send_leave/ request.
|
||||||
|
@ -1358,26 +1350,14 @@ class FederationHandler(BaseHandler):
|
||||||
defer.returnValue((origin, event))
|
defer.returnValue((origin, event))
|
||||||
|
|
||||||
def _sign_event(self, event):
|
def _sign_event(self, event):
|
||||||
event.internal_metadata.outlier = False
|
event.signatures.update(
|
||||||
|
compute_event_signature(
|
||||||
builder = self.event_builder_factory.new(
|
event,
|
||||||
unfreeze(event.get_pdu_json())
|
self.hs.hostname,
|
||||||
|
self.hs.config.signing_key[0]
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
builder.event_id = self.event_builder_factory.create_event_id()
|
|
||||||
builder.origin = self.hs.hostname
|
|
||||||
|
|
||||||
if not hasattr(event, "signatures"):
|
|
||||||
builder.signatures = {}
|
|
||||||
|
|
||||||
add_hashes_and_signatures(
|
|
||||||
builder,
|
|
||||||
self.hs.hostname,
|
|
||||||
self.hs.config.signing_key[0],
|
|
||||||
)
|
|
||||||
|
|
||||||
return builder.build()
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
@log_function
|
@log_function
|
||||||
def on_make_leave_request(self, room_id, user_id):
|
def on_make_leave_request(self, room_id, user_id):
|
||||||
|
|
|
@ -591,10 +591,7 @@ class RoomMemberStore(RoomMemberWorkerStore):
|
||||||
# i.e., its something that has just happened.
|
# i.e., its something that has just happened.
|
||||||
# The only current event that can also be an outlier is if its an
|
# The only current event that can also be an outlier is if its an
|
||||||
# invite that has come in across federation.
|
# invite that has come in across federation.
|
||||||
is_new_state = not backfilled and (
|
is_new_state = not backfilled
|
||||||
not event.internal_metadata.is_outlier()
|
|
||||||
or event.internal_metadata.is_invite_from_remote()
|
|
||||||
)
|
|
||||||
is_mine = self.hs.is_mine_id(event.state_key)
|
is_mine = self.hs.is_mine_id(event.state_key)
|
||||||
if is_new_state and is_mine:
|
if is_new_state and is_mine:
|
||||||
if event.membership == Membership.INVITE:
|
if event.membership == Membership.INVITE:
|
||||||
|
|
Loading…
Reference in a new issue