Depublish a room from the public rooms list when it is upgraded (#6232)

This commit is contained in:
Andrew Morgan 2019-11-01 10:28:09 +00:00 committed by GitHub
parent 53d7680e32
commit ace947e8da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 93 additions and 31 deletions

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

@ -0,0 +1 @@
Remove a room from a server's public rooms list on room upgrade.

View file

@ -555,7 +555,7 @@ class FederationClient(FederationBase):
Note that this does not append any events to any graphs. Note that this does not append any events to any graphs.
Args: Args:
destinations (str): Candidate homeservers which are probably destinations (Iterable[str]): Candidate homeservers which are probably
participating in the room. participating in the room.
room_id (str): The room in which the event will happen. room_id (str): The room in which the event will happen.
user_id (str): The user whose membership is being evented. user_id (str): The user whose membership is being evented.

View file

@ -1106,7 +1106,7 @@ class FederationHandler(BaseHandler):
@defer.inlineCallbacks @defer.inlineCallbacks
def do_invite_join(self, target_hosts, room_id, joinee, content): def do_invite_join(self, target_hosts, room_id, joinee, content):
""" Attempts to join the `joinee` to the room `room_id` via the """ Attempts to join the `joinee` to the room `room_id` via the
server `target_host`. servers contained in `target_hosts`.
This first triggers a /make_join/ request that returns a partial This first triggers a /make_join/ request that returns a partial
event that we can fill out and sign. This is then sent to the event that we can fill out and sign. This is then sent to the
@ -1115,6 +1115,15 @@ class FederationHandler(BaseHandler):
We suspend processing of any received events from this room until we We suspend processing of any received events from this room until we
have finished processing the join. have finished processing the join.
Args:
target_hosts (Iterable[str]): List of servers to attempt to join the room with.
room_id (str): The ID of the room to join.
joinee (str): The User ID of the joining user.
content (dict): The event content to use for the join event.
""" """
logger.debug("Joining %s to %s", joinee, room_id) logger.debug("Joining %s to %s", joinee, room_id)
@ -1174,6 +1183,22 @@ class FederationHandler(BaseHandler):
yield self._persist_auth_tree(origin, auth_chain, state, event) yield self._persist_auth_tree(origin, auth_chain, state, event)
# Check whether this room is the result of an upgrade of a room we already know
# about. If so, migrate over user information
predecessor = yield self.store.get_room_predecessor(room_id)
if not predecessor:
return
old_room_id = predecessor["room_id"]
logger.debug(
"Found predecessor for %s during remote join: %s", room_id, old_room_id
)
# We retrieve the room member handler here as to not cause a cyclic dependency
member_handler = self.hs.get_room_member_handler()
yield member_handler.transfer_room_state_on_room_upgrade(
old_room_id, room_id
)
logger.debug("Finished joining %s to %s", joinee, room_id) logger.debug("Finished joining %s to %s", joinee, room_id)
finally: finally:
room_queue = self.room_queues[room_id] room_queue = self.room_queues[room_id]
@ -2442,6 +2467,8 @@ class FederationHandler(BaseHandler):
raise e raise e
yield self._check_signature(event, context) yield self._check_signature(event, context)
# We retrieve the room member handler here as to not cause a cyclic dependency
member_handler = self.hs.get_room_member_handler() member_handler = self.hs.get_room_member_handler()
yield member_handler.send_membership_event(None, event, context) yield member_handler.send_membership_event(None, event, context)
else: else:
@ -2502,6 +2529,7 @@ class FederationHandler(BaseHandler):
# though the sender isn't a local user. # though the sender isn't a local user.
event.internal_metadata.send_on_behalf_of = get_domain_from_id(event.sender) event.internal_metadata.send_on_behalf_of = get_domain_from_id(event.sender)
# We retrieve the room member handler here as to not cause a cyclic dependency
member_handler = self.hs.get_room_member_handler() member_handler = self.hs.get_room_member_handler()
yield member_handler.send_membership_event(None, event, context) yield member_handler.send_membership_event(None, event, context)

View file

@ -129,6 +129,7 @@ class RoomCreationHandler(BaseHandler):
old_room_id, old_room_id,
new_version, # args for _upgrade_room new_version, # args for _upgrade_room
) )
return ret return ret
@defer.inlineCallbacks @defer.inlineCallbacks
@ -189,7 +190,12 @@ class RoomCreationHandler(BaseHandler):
requester, old_room_id, new_room_id, old_room_state requester, old_room_id, new_room_id, old_room_state
) )
# and finally, shut down the PLs in the old room, and update them in the new # Copy over user push rules, tags and migrate room directory state
yield self.room_member_handler.transfer_room_state_on_room_upgrade(
old_room_id, new_room_id
)
# finally, shut down the PLs in the old room, and update them in the new
# room. # room.
yield self._update_upgraded_room_pls( yield self._update_upgraded_room_pls(
requester, old_room_id, new_room_id, old_room_state requester, old_room_id, new_room_id, old_room_state

View file

@ -203,10 +203,6 @@ class RoomMemberHandler(object):
prev_member_event = yield self.store.get_event(prev_member_event_id) prev_member_event = yield self.store.get_event(prev_member_event_id)
newly_joined = prev_member_event.membership != Membership.JOIN newly_joined = prev_member_event.membership != Membership.JOIN
if newly_joined: if newly_joined:
# Copy over user state if we're joining an upgraded room
yield self.copy_user_state_if_room_upgrade(
room_id, requester.user.to_string()
)
yield self._user_joined_room(target, room_id) yield self._user_joined_room(target, room_id)
elif event.membership == Membership.LEAVE: elif event.membership == Membership.LEAVE:
if prev_member_event_id: if prev_member_event_id:
@ -455,11 +451,6 @@ class RoomMemberHandler(object):
requester, remote_room_hosts, room_id, target, content requester, remote_room_hosts, room_id, target, content
) )
# Copy over user state if this is a join on an remote upgraded room
yield self.copy_user_state_if_room_upgrade(
room_id, requester.user.to_string()
)
return remote_join_response return remote_join_response
elif effective_membership_state == Membership.LEAVE: elif effective_membership_state == Membership.LEAVE:
@ -498,36 +489,72 @@ class RoomMemberHandler(object):
return res return res
@defer.inlineCallbacks @defer.inlineCallbacks
def copy_user_state_if_room_upgrade(self, new_room_id, user_id): def transfer_room_state_on_room_upgrade(self, old_room_id, room_id):
"""Copy user-specific information when they join a new room if that new room is the """Upon our server becoming aware of an upgraded room, either by upgrading a room
result of a room upgrade ourselves or joining one, we can transfer over information from the previous room.
Copies user state (tags/push rules) for every local user that was in the old room, as
well as migrating the room directory state.
Args: Args:
new_room_id (str): The ID of the room the user is joining old_room_id (str): The ID of the old room
user_id (str): The ID of the user
room_id (str): The ID of the new room
Returns:
Deferred
"""
# Find all local users that were in the old room and copy over each user's state
users = yield self.store.get_users_in_room(old_room_id)
yield self.copy_user_state_on_room_upgrade(old_room_id, room_id, users)
# Add new room to the room directory if the old room was there
# Remove old room from the room directory
old_room = yield self.store.get_room(old_room_id)
if old_room and old_room["is_public"]:
yield self.store.set_room_is_public(old_room_id, False)
yield self.store.set_room_is_public(room_id, True)
@defer.inlineCallbacks
def copy_user_state_on_room_upgrade(self, old_room_id, new_room_id, user_ids):
"""Copy user-specific information when they join a new room when that new room is the
result of a room upgrade
Args:
old_room_id (str): The ID of upgraded room
new_room_id (str): The ID of the new room
user_ids (Iterable[str]): User IDs to copy state for
Returns: Returns:
Deferred Deferred
""" """
# Check if the new room is an upgraded room
predecessor = yield self.store.get_room_predecessor(new_room_id)
if not predecessor:
return
logger.debug( logger.debug(
"Found predecessor for %s: %s. Copying over room tags and push " "rules", "Copying over room tags and push rules from %s to %s for users %s",
old_room_id,
new_room_id, new_room_id,
predecessor, user_ids,
) )
# It is an upgraded room. Copy over old tags for user_id in user_ids:
yield self.copy_room_tags_and_direct_to_room( try:
predecessor["room_id"], new_room_id, user_id # It is an upgraded room. Copy over old tags
) yield self.copy_room_tags_and_direct_to_room(
# Copy over push rules old_room_id, new_room_id, user_id
yield self.store.copy_push_rules_from_room_to_room_for_user( )
predecessor["room_id"], new_room_id, user_id # Copy over push rules
) yield self.store.copy_push_rules_from_room_to_room_for_user(
old_room_id, new_room_id, user_id
)
except Exception:
logger.exception(
"Error copying tags and/or push rules from rooms %s to %s for user %s. "
"Skipping...",
old_room_id,
new_room_id,
user_id,
)
continue
@defer.inlineCallbacks @defer.inlineCallbacks
def send_membership_event(self, requester, event, context, ratelimit=True): def send_membership_event(self, requester, event, context, ratelimit=True):