Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Convert directory handler to async/await #7727

Merged
merged 4 commits into from
Jun 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/7727.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Convert directory handler to async/await.
68 changes: 29 additions & 39 deletions synapse/handlers/directory.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
import string
from typing import Iterable, List, Optional

from twisted.internet import defer

from synapse.api.constants import MAX_ALIAS_LENGTH, EventTypes
from synapse.api.errors import (
AuthError,
Expand Down Expand Up @@ -55,8 +53,7 @@ def __init__(self, hs):

self.spam_checker = hs.get_spam_checker()

@defer.inlineCallbacks
def _create_association(
async def _create_association(
self,
room_alias: RoomAlias,
room_id: str,
Expand All @@ -76,13 +73,13 @@ def _create_association(
# TODO(erikj): Add transactions.
# TODO(erikj): Check if there is a current association.
if not servers:
users = yield self.state.get_current_users_in_room(room_id)
users = await self.state.get_current_users_in_room(room_id)
servers = {get_domain_from_id(u) for u in users}

if not servers:
raise SynapseError(400, "Failed to get server list")

yield self.store.create_room_alias_association(
await self.store.create_room_alias_association(
room_alias, room_id, servers, creator=creator
)

Expand All @@ -93,7 +90,7 @@ async def create_association(
room_id: str,
servers: Optional[List[str]] = None,
check_membership: bool = True,
):
) -> None:
"""Attempt to create a new alias
Args:
Expand All @@ -103,9 +100,6 @@ async def create_association(
servers: Iterable of servers that others servers should try and join via
check_membership: Whether to check if the user is in the room
before the alias can be set (if the server's config requires it).
Returns:
Deferred
"""

user_id = requester.user.to_string()
Expand Down Expand Up @@ -148,7 +142,7 @@ async def create_association(
# per alias creation rule?
raise SynapseError(403, "Not allowed to create alias")

can_create = await self.can_modify_alias(room_alias, user_id=user_id)
can_create = self.can_modify_alias(room_alias, user_id=user_id)
if not can_create:
raise AuthError(
400,
Expand All @@ -158,7 +152,9 @@ async def create_association(

await self._create_association(room_alias, room_id, servers, creator=user_id)

async def delete_association(self, requester: Requester, room_alias: RoomAlias):
async def delete_association(
self, requester: Requester, room_alias: RoomAlias
) -> str:
"""Remove an alias from the directory
(this is only meant for human users; AS users should call
Expand All @@ -169,7 +165,7 @@ async def delete_association(self, requester: Requester, room_alias: RoomAlias):
room_alias
Returns:
Deferred[unicode]: room id that the alias used to point to
room id that the alias used to point to
Raises:
NotFoundError: if the alias doesn't exist
Expand All @@ -191,7 +187,7 @@ async def delete_association(self, requester: Requester, room_alias: RoomAlias):
if not can_delete:
raise AuthError(403, "You don't have permission to delete the alias.")

can_delete = await self.can_modify_alias(room_alias, user_id=user_id)
can_delete = self.can_modify_alias(room_alias, user_id=user_id)
if not can_delete:
raise SynapseError(
400,
Expand All @@ -208,8 +204,7 @@ async def delete_association(self, requester: Requester, room_alias: RoomAlias):

return room_id

@defer.inlineCallbacks
def delete_appservice_association(
async def delete_appservice_association(
self, service: ApplicationService, room_alias: RoomAlias
):
if not service.is_interested_in_alias(room_alias.to_string()):
Expand All @@ -218,29 +213,27 @@ def delete_appservice_association(
"This application service has not reserved this kind of alias",
errcode=Codes.EXCLUSIVE,
)
yield self._delete_association(room_alias)
await self._delete_association(room_alias)

@defer.inlineCallbacks
def _delete_association(self, room_alias: RoomAlias):
async def _delete_association(self, room_alias: RoomAlias):
if not self.hs.is_mine(room_alias):
raise SynapseError(400, "Room alias must be local")

room_id = yield self.store.delete_room_alias(room_alias)
room_id = await self.store.delete_room_alias(room_alias)

return room_id

@defer.inlineCallbacks
def get_association(self, room_alias: RoomAlias):
async def get_association(self, room_alias: RoomAlias):
room_id = None
if self.hs.is_mine(room_alias):
result = yield self.get_association_from_room_alias(room_alias)
result = await self.get_association_from_room_alias(room_alias)

if result:
room_id = result.room_id
servers = result.servers
else:
try:
result = yield self.federation.make_query(
result = await self.federation.make_query(
destination=room_alias.domain,
query_type="directory",
args={"room_alias": room_alias.to_string()},
Expand All @@ -265,7 +258,7 @@ def get_association(self, room_alias: RoomAlias):
Codes.NOT_FOUND,
)

users = yield self.state.get_current_users_in_room(room_id)
users = await self.state.get_current_users_in_room(room_id)
extra_servers = {get_domain_from_id(u) for u in users}
servers = set(extra_servers) | set(servers)

Expand All @@ -277,13 +270,12 @@ def get_association(self, room_alias: RoomAlias):

return {"room_id": room_id, "servers": servers}

@defer.inlineCallbacks
def on_directory_query(self, args):
async def on_directory_query(self, args):
room_alias = RoomAlias.from_string(args["room_alias"])
if not self.hs.is_mine(room_alias):
raise SynapseError(400, "Room Alias is not hosted on this homeserver")

result = yield self.get_association_from_room_alias(room_alias)
result = await self.get_association_from_room_alias(room_alias)

if result is not None:
return {"room_id": result.room_id, "servers": result.servers}
Expand Down Expand Up @@ -344,16 +336,15 @@ async def _update_canonical_alias(
ratelimit=False,
)

@defer.inlineCallbacks
def get_association_from_room_alias(self, room_alias: RoomAlias):
result = yield self.store.get_association_from_room_alias(room_alias)
async def get_association_from_room_alias(self, room_alias: RoomAlias):
result = await self.store.get_association_from_room_alias(room_alias)
if not result:
# Query AS to see if it exists
as_handler = self.appservice_handler
result = yield as_handler.query_room_alias_exists(room_alias)
result = await as_handler.query_room_alias_exists(room_alias)
return result

def can_modify_alias(self, alias: RoomAlias, user_id: Optional[str] = None):
def can_modify_alias(self, alias: RoomAlias, user_id: Optional[str] = None) -> bool:
# Any application service "interested" in an alias they are regexing on
# can modify the alias.
# Users can only modify the alias if ALL the interested services have
Expand All @@ -366,12 +357,12 @@ def can_modify_alias(self, alias: RoomAlias, user_id: Optional[str] = None):
for service in interested_services:
if user_id == service.sender:
# this user IS the app service so they can do whatever they like
return defer.succeed(True)
return True
elif service.is_exclusive_alias(alias.to_string()):
# another service has an exclusive lock on this alias.
return defer.succeed(False)
return False
# either no interested services, or no service with an exclusive lock
return defer.succeed(True)
return True

async def _user_can_delete_alias(self, alias: RoomAlias, user_id: str):
"""Determine whether a user can delete an alias.
Expand Down Expand Up @@ -459,8 +450,7 @@ async def edit_published_room_list(

await self.store.set_room_is_public(room_id, making_public)

@defer.inlineCallbacks
def edit_published_appservice_room_list(
async def edit_published_appservice_room_list(
self, appservice_id: str, network_id: str, room_id: str, visibility: str
):
"""Add or remove a room from the appservice/network specific public
Expand All @@ -475,7 +465,7 @@ def edit_published_appservice_room_list(
if visibility not in ["public", "private"]:
raise SynapseError(400, "Invalid visibility setting")

yield self.store.set_room_is_public_appservice(
await self.store.set_room_is_public_appservice(
room_id, appservice_id, network_id, visibility == "public"
)

Expand Down
4 changes: 3 additions & 1 deletion synapse/handlers/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,9 @@ def _validate_canonical_alias(
"""
room_alias = RoomAlias.from_string(room_alias_str)
try:
mapping = yield directory_handler.get_association(room_alias)
mapping = yield defer.ensureDeferred(
directory_handler.get_association(room_alias)
)
except SynapseError as e:
# Turn M_NOT_FOUND errors into M_BAD_ALIAS errors.
if e.errcode == Codes.NOT_FOUND:
Expand Down