forked from MirrorHub/synapse
Merge pull request #4405 from matrix-org/erikj/fixup_rejecting_invites
Store rejected remote invite events as outliers
This commit is contained in:
commit
80bcca659e
5 changed files with 35 additions and 39 deletions
1
changelog.d/4405.bugfix
Normal file
1
changelog.d/4405.bugfix
Normal file
|
@ -0,0 +1 @@
|
|||
Fix bug when rejecting remote invites
|
|
@ -42,8 +42,13 @@ class _EventInternalMetadata(object):
|
|||
def is_outlier(self):
|
||||
return getattr(self, "outlier", False)
|
||||
|
||||
def is_invite_from_remote(self):
|
||||
return getattr(self, "invite_from_remote", False)
|
||||
def is_out_of_band_membership(self):
|
||||
"""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):
|
||||
"""Whether this server should send the event on behalf of another server.
|
||||
|
|
|
@ -32,7 +32,7 @@ from synapse.api.errors import (
|
|||
HttpResponseException,
|
||||
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.util import logcontext, unwrapFirstError
|
||||
from synapse.util.caches.expiringcache import ExpiringCache
|
||||
|
@ -66,6 +66,8 @@ class FederationClient(FederationBase):
|
|||
self.state = hs.get_state_handler()
|
||||
self.transport_layer = hs.get_federation_transport_client()
|
||||
|
||||
self.event_builder_factory = hs.get_event_builder_factory()
|
||||
|
||||
self._get_pdu_cache = ExpiringCache(
|
||||
cache_name="get_pdu_cache",
|
||||
clock=self._clock,
|
||||
|
@ -522,6 +524,8 @@ class FederationClient(FederationBase):
|
|||
Does so by asking one of the already participating servers to create an
|
||||
event with proper context.
|
||||
|
||||
Returns a fully signed and hashed event.
|
||||
|
||||
Note that this does not append any events to any graphs.
|
||||
|
||||
Args:
|
||||
|
@ -536,8 +540,9 @@ class FederationClient(FederationBase):
|
|||
params (dict[str, str|Iterable[str]]): Query parameters to include in the
|
||||
request.
|
||||
Return:
|
||||
Deferred: resolves to a tuple of (origin (str), event (object))
|
||||
where origin is the remote homeserver which generated the event.
|
||||
Deferred[tuple[str, FrozenEvent]]: resolves to a tuple of `origin`
|
||||
and event where origin is the remote homeserver which generated
|
||||
the event.
|
||||
|
||||
Fails with a ``SynapseError`` if the chosen remote server
|
||||
returns a 300/400 code.
|
||||
|
@ -571,7 +576,18 @@ class FederationClient(FederationBase):
|
|||
if "prev_state" not in pdu_dict:
|
||||
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(
|
||||
(destination, ev)
|
||||
|
|
|
@ -43,10 +43,7 @@ from synapse.api.errors import (
|
|||
StoreError,
|
||||
SynapseError,
|
||||
)
|
||||
from synapse.crypto.event_signing import (
|
||||
add_hashes_and_signatures,
|
||||
compute_event_signature,
|
||||
)
|
||||
from synapse.crypto.event_signing import compute_event_signature
|
||||
from synapse.events.validator import EventValidator
|
||||
from synapse.replication.http.federation import (
|
||||
ReplicationCleanRoomRestServlet,
|
||||
|
@ -58,7 +55,6 @@ from synapse.types import UserID, get_domain_from_id
|
|||
from synapse.util import logcontext, unwrapFirstError
|
||||
from synapse.util.async_helpers import Linearizer
|
||||
from synapse.util.distributor import user_joined_room
|
||||
from synapse.util.frozenutils import unfreeze
|
||||
from synapse.util.logutils import log_function
|
||||
from synapse.util.retryutils import NotRetryingDestination
|
||||
from synapse.visibility import filter_events_for_server
|
||||
|
@ -1083,7 +1079,6 @@ class FederationHandler(BaseHandler):
|
|||
handled_events = set()
|
||||
|
||||
try:
|
||||
event = self._sign_event(event)
|
||||
# Try the host we successfully got a response to /make_join/
|
||||
# request first.
|
||||
try:
|
||||
|
@ -1287,7 +1282,7 @@ class FederationHandler(BaseHandler):
|
|||
)
|
||||
|
||||
event.internal_metadata.outlier = True
|
||||
event.internal_metadata.invite_from_remote = True
|
||||
event.internal_metadata.out_of_band_membership = True
|
||||
|
||||
event.signatures.update(
|
||||
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
|
||||
# even in the room.
|
||||
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
|
||||
# the /send_leave/ request.
|
||||
|
@ -1357,27 +1352,6 @@ class FederationHandler(BaseHandler):
|
|||
assert(event.room_id == room_id)
|
||||
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
|
||||
@log_function
|
||||
def on_make_leave_request(self, room_id, user_id):
|
||||
|
|
|
@ -588,12 +588,12 @@ class RoomMemberStore(RoomMemberWorkerStore):
|
|||
)
|
||||
|
||||
# We update the local_invites table only if the event is "current",
|
||||
# i.e., its something that has just happened.
|
||||
# The only current event that can also be an outlier is if its an
|
||||
# invite that has come in across federation.
|
||||
# i.e., its something that has just happened. If the event is an
|
||||
# outlier it is only current if its an "out of band membership",
|
||||
# like a remote invite or a rejection of a remote invite.
|
||||
is_new_state = not backfilled and (
|
||||
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)
|
||||
if is_new_state and is_mine:
|
||||
|
|
Loading…
Reference in a new issue