1
0

Merge pull request #4218 from matrix-org/travis/account-merging

Proof of concept for auto-accepting invites on merged accounts
This commit is contained in:
Travis Ralston
2018-11-22 09:00:25 -07:00
committed by GitHub
2 changed files with 72 additions and 2 deletions
+33 -1
View File
@@ -48,13 +48,14 @@ from synapse.crypto.event_signing import (
compute_event_signature,
)
from synapse.events.validator import EventValidator
from synapse.metrics.background_process_metrics import run_as_background_process
from synapse.replication.http.federation import (
ReplicationCleanRoomRestServlet,
ReplicationFederationSendEventsRestServlet,
)
from synapse.replication.http.membership import ReplicationUserJoinedLeftRoomRestServlet
from synapse.state import StateResolutionStore, resolve_events_with_store
from synapse.types import UserID, get_domain_from_id
from synapse.types import UserID, get_domain_from_id, create_requester
from synapse.util import logcontext, unwrapFirstError
from synapse.util.async_helpers import Linearizer
from synapse.util.distributor import user_joined_room
@@ -105,6 +106,7 @@ class FederationHandler(BaseHandler):
self.hs = hs
self.clock = hs.get_clock()
self.store = hs.get_datastore() # type: synapse.storage.DataStore
self.federation_client = hs.get_federation_client()
self.state_handler = hs.get_state_handler()
@@ -1300,8 +1302,38 @@ class FederationHandler(BaseHandler):
context = yield self.state_handler.compute_event_context(event)
yield self.persist_events_and_notify([(event, context)])
sender = UserID.from_string(event.sender)
target = UserID.from_string(event.state_key)
if (sender.localpart == target.localpart):
run_as_background_process(
"_auto_accept_invite",
self._auto_accept_invite,
sender, target, event.room_id,
)
defer.returnValue(event)
@defer.inlineCallbacks
def _auto_accept_invite(self, sender, target, room_id):
joined = False
for attempt in range(0, 10):
try:
yield self.hs.get_room_member_handler().update_membership(
requester=create_requester(target.to_string()),
target=target,
room_id=room_id,
action="join",
)
joined = True
break
except Exception:
# We're going to retry, but we should log the error
logger.exception("Error auto-accepting invite on attempt %d" % attempt)
yield self.clock.sleep(1)
if not joined:
logger.error("Giving up on trying to auto-accept invite: too many attempts")
@defer.inlineCallbacks
def do_remotely_reject_invite(self, target_hosts, room_id, user_id):
origin, event = yield self._make_and_verify_event(
+39 -1
View File
@@ -29,7 +29,8 @@ import synapse.server
import synapse.types
from synapse.api.constants import EventTypes, Membership
from synapse.api.errors import AuthError, Codes, SynapseError
from synapse.types import RoomID, UserID
from synapse.types import RoomID, UserID, RoomAlias
from synapse.util import logcontext
from synapse.util.async_helpers import Linearizer
from synapse.util.distributor import user_joined_room, user_left_room
@@ -416,6 +417,10 @@ class RoomMemberHandler(object):
ret = yield self._remote_join(
requester, remote_room_hosts, room_id, target, content
)
logcontext.run_in_background(
self._send_merged_user_invites,
requester, room_id,
)
defer.returnValue(ret)
elif effective_membership_state == Membership.LEAVE:
@@ -450,8 +455,41 @@ class RoomMemberHandler(object):
prev_events_and_hashes=prev_events_and_hashes,
content=content,
)
if effective_membership_state == Membership.JOIN:
logcontext.run_in_background(
self._send_merged_user_invites,
requester, room_id,
)
defer.returnValue(res)
@defer.inlineCallbacks
def _send_merged_user_invites(self, requester, room_id):
profile_alias = "#_profile_" + requester.user.localpart + ":" + self.hs.hostname
profile_alias = RoomAlias.from_string(profile_alias)
profile_room_id, remote_room_hosts = yield self.lookup_room_alias(profile_alias)
if profile_room_id:
linked_accounts = yield self.state_handler.get_current_state(
room_id=profile_room_id.to_string(),
event_type="m.linked_accounts",
state_key="",
)
if not linked_accounts or not linked_accounts.content['all_children']:
return
for child_id in linked_accounts.content['all_children']:
child = UserID.from_string(child_id)
if self.hs.is_mine(child) or child_id == requester.user.to_string():
# TODO: Handle auto-invite for local users (not a priority)
continue
try:
yield self.update_membership(
requester=requester,
target=child,
room_id=room_id,
action="invite",
)
except Exception:
logger.exception("Failed to invite %s to %s" % (child_id, room_id))
@defer.inlineCallbacks
def send_membership_event(
self,