Merge pull request #4405 from matrix-org/erikj/fixup_rejecting_invites

Store rejected remote invite events as outliers
This commit is contained in:
Erik Johnston 2019-01-24 18:33:27 +00:00 committed by GitHub
commit 80bcca659e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 35 additions and 39 deletions

1
changelog.d/4405.bugfix Normal file
View file

@ -0,0 +1 @@
Fix bug when rejecting remote invites

View file

@ -42,8 +42,13 @@ class _EventInternalMetadata(object):
def is_outlier(self): def is_outlier(self):
return getattr(self, "outlier", False) return getattr(self, "outlier", False)
def is_invite_from_remote(self): def is_out_of_band_membership(self):
return getattr(self, "invite_from_remote", False) """Whether this is an out of band membership, like an invite or an invite
rejection. This is needed as those events are marked as outliers, but
they still need to be processed as if they're new events (e.g. updating
invite state in the database, relaying to clients, etc).
"""
return getattr(self, "out_of_band_membership", False)
def get_send_on_behalf_of(self): def get_send_on_behalf_of(self):
"""Whether this server should send the event on behalf of another server. """Whether this server should send the event on behalf of another server.

View file

@ -32,7 +32,7 @@ from synapse.api.errors import (
HttpResponseException, HttpResponseException,
SynapseError, SynapseError,
) )
from synapse.events import builder from synapse.crypto.event_signing import add_hashes_and_signatures
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 +66,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,
@ -522,6 +524,8 @@ class FederationClient(FederationBase):
Does so by asking one of the already participating servers to create an Does so by asking one of the already participating servers to create an
event with proper context. event with proper context.
Returns a fully signed and hashed event.
Note that this does not append any events to any graphs. Note that this does not append any events to any graphs.
Args: Args:
@ -536,8 +540,9 @@ class FederationClient(FederationBase):
params (dict[str, str|Iterable[str]]): Query parameters to include in the params (dict[str, str|Iterable[str]]): Query parameters to include in the
request. request.
Return: Return:
Deferred: resolves to a tuple of (origin (str), event (object)) Deferred[tuple[str, FrozenEvent]]: resolves to a tuple of `origin`
where origin is the remote homeserver which generated the event. and event where origin is the remote homeserver which generated
the event.
Fails with a ``SynapseError`` if the chosen remote server Fails with a ``SynapseError`` if the chosen remote server
returns a 300/400 code. returns a 300/400 code.
@ -571,7 +576,18 @@ 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)
builder = self.event_builder_factory.new(pdu_dict)
add_hashes_and_signatures(
builder,
self.hs.hostname,
self.hs.config.signing_key[0]
)
ev = builder.build()
defer.returnValue( defer.returnValue(
(destination, ev) (destination, ev)

View file

@ -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,6 @@ class FederationHandler(BaseHandler):
handled_events = set() handled_events = set()
try: try:
event = self._sign_event(event)
# 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:
@ -1287,7 +1282,7 @@ class FederationHandler(BaseHandler):
) )
event.internal_metadata.outlier = True event.internal_metadata.outlier = True
event.internal_metadata.invite_from_remote = True event.internal_metadata.out_of_band_membership = True
event.signatures.update( event.signatures.update(
compute_event_signature( compute_event_signature(
@ -1313,7 +1308,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) event.internal_metadata.out_of_band_membership = True
# 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.
@ -1357,27 +1352,6 @@ class FederationHandler(BaseHandler):
assert(event.room_id == room_id) assert(event.room_id == room_id)
defer.returnValue((origin, event)) defer.returnValue((origin, event))
def _sign_event(self, event):
event.internal_metadata.outlier = False
builder = self.event_builder_factory.new(
unfreeze(event.get_pdu_json())
)
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):

View file

@ -588,12 +588,12 @@ class RoomMemberStore(RoomMemberWorkerStore):
) )
# We update the local_invites table only if the event is "current", # We update the local_invites table only if the event is "current",
# i.e., its something that has just happened. # i.e., its something that has just happened. If the event is an
# The only current event that can also be an outlier is if its an # outlier it is only current if its an "out of band membership",
# invite that has come in across federation. # like a remote invite or a rejection of a remote invite.
is_new_state = not backfilled and ( is_new_state = not backfilled and (
not event.internal_metadata.is_outlier() not event.internal_metadata.is_outlier()
or event.internal_metadata.is_invite_from_remote() or event.internal_metadata.is_out_of_band_membership()
) )
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: