summary refs log tree commit diff
path: root/synapse
diff options
context:
space:
mode:
Diffstat (limited to 'synapse')
-rw-r--r--synapse/api/errors.py5
-rw-r--r--synapse/handlers/profile.py11
-rw-r--r--synapse/handlers/room.py44
-rw-r--r--synapse/rest/client/v1/room.py68
-rw-r--r--synapse/types.py14
5 files changed, 69 insertions, 73 deletions
diff --git a/synapse/api/errors.py b/synapse/api/errors.py
index 0c7858f78d..b106fbed6d 100644
--- a/synapse/api/errors.py
+++ b/synapse/api/errors.py
@@ -84,11 +84,6 @@ class RegistrationError(SynapseError):
     pass
 
 
-class BadIdentifierError(SynapseError):
-    """An error indicating an identifier couldn't be parsed."""
-    pass
-
-
 class UnrecognizedRequestError(SynapseError):
     """An error indicating we don't understand the request you're trying to make"""
     def __init__(self, *args, **kwargs):
diff --git a/synapse/handlers/profile.py b/synapse/handlers/profile.py
index 32af622733..629e6e3594 100644
--- a/synapse/handlers/profile.py
+++ b/synapse/handlers/profile.py
@@ -169,15 +169,8 @@ class ProfileHandler(BaseHandler):
             consumeErrors=True
         ).addErrback(unwrapFirstError)
 
-        if displayname is None:
-            del state["displayname"]
-        else:
-            state["displayname"] = displayname
-
-        if avatar_url is None:
-            del state["avatar_url"]
-        else:
-            state["avatar_url"] = avatar_url
+        state["displayname"] = displayname
+        state["avatar_url"] = avatar_url
 
         defer.returnValue(None)
 
diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py
index 2950ed14e4..b2de2cd0c0 100644
--- a/synapse/handlers/room.py
+++ b/synapse/handlers/room.py
@@ -527,17 +527,7 @@ class RoomMemberHandler(BaseHandler):
         defer.returnValue({"room_id": room_id})
 
     @defer.inlineCallbacks
-    def lookup_room_alias(self, room_alias):
-        """
-        Gets the room ID for an alias.
-
-        Args:
-            room_alias (str): The room alias to look up.
-        Returns:
-            A tuple of the room ID (str) and the hosts hosting the room ([str])
-        Raises:
-            SynapseError if the room couldn't be looked up.
-        """
+    def join_room_alias(self, joinee, room_alias, content={}):
         directory_handler = self.hs.get_handlers().directory_handler
         mapping = yield directory_handler.get_association(room_alias)
 
@@ -549,40 +539,24 @@ class RoomMemberHandler(BaseHandler):
         if not hosts:
             raise SynapseError(404, "No known servers")
 
-        defer.returnValue((room_id, hosts))
-
-    @defer.inlineCallbacks
-    def do_join(self, requester, room_id, hosts=None):
-        """
-        Joins requester to room_id.
-
-        Args:
-            requester (Requester): The user joining the room.
-            room_id (str): The room ID (not alias) being joined.
-            hosts ([str]): A list of hosts which are hopefully in the room.
-        Raises:
-            SynapseError if the room couldn't be joined.
-        """
-        hosts = hosts or []
-
-        content = {"membership": Membership.JOIN}
-        if requester.is_guest:
-            content["kind"] = "guest"
-
-        yield collect_presencelike_data(self.distributor, requester.user, content)
+        # If event doesn't include a display name, add one.
+        yield collect_presencelike_data(self.distributor, joinee, content)
 
+        content.update({"membership": Membership.JOIN})
         builder = self.event_builder_factory.new({
             "type": EventTypes.Member,
-            "state_key": requester.user.to_string(),
+            "state_key": joinee.to_string(),
             "room_id": room_id,
-            "sender": requester.user.to_string(),
-            "membership": Membership.JOIN,  # For backwards compatibility
+            "sender": joinee.to_string(),
+            "membership": Membership.JOIN,
             "content": content,
         })
         event, context = yield self._create_new_client_event(builder)
 
         yield self._do_join(event, context, room_hosts=hosts)
 
+        defer.returnValue({"room_id": room_id})
+
     @defer.inlineCallbacks
     def _do_join(self, event, context, room_hosts=None):
         room_id = event.room_id
diff --git a/synapse/rest/client/v1/room.py b/synapse/rest/client/v1/room.py
index 1dd33b0a56..81bfe377bd 100644
--- a/synapse/rest/client/v1/room.py
+++ b/synapse/rest/client/v1/room.py
@@ -216,7 +216,11 @@ class RoomSendEventRestServlet(ClientV1RestServlet):
 
 # TODO: Needs unit testing for room ID + alias joins
 class JoinRoomAliasServlet(ClientV1RestServlet):
-    PATTERNS = client_path_patterns("/join/(?P<room_identifier>[^/]*)$")
+
+    def register(self, http_server):
+        # /join/$room_identifier[/$txn_id]
+        PATTERNS = ("/join/(?P<room_identifier>[^/]*)")
+        register_txn_path(self, PATTERNS, http_server)
 
     @defer.inlineCallbacks
     def on_POST(self, request, room_identifier, txn_id=None):
@@ -225,22 +229,60 @@ class JoinRoomAliasServlet(ClientV1RestServlet):
             allow_guest=True,
         )
 
-        handler = self.handlers.room_member_handler
+        # the identifier could be a room alias or a room id. Try one then the
+        # other if it fails to parse, without swallowing other valid
+        # SynapseErrors.
 
-        room_id = None
-        hosts = []
-        if RoomAlias.is_valid(room_identifier):
-            room_alias = RoomAlias.from_string(room_identifier)
-            room_id, hosts = yield handler.lookup_room_alias(room_alias)
-        else:
-            room_id = RoomID.from_string(room_identifier).to_string()
+        identifier = None
+        is_room_alias = False
+        try:
+            identifier = RoomAlias.from_string(room_identifier)
+            is_room_alias = True
+        except SynapseError:
+            identifier = RoomID.from_string(room_identifier)
 
         # TODO: Support for specifying the home server to join with?
 
-        yield handler.do_join(
-            requester, room_id, hosts=hosts
-        )
-        defer.returnValue((200, {"room_id": room_id}))
+        if is_room_alias:
+            handler = self.handlers.room_member_handler
+            ret_dict = yield handler.join_room_alias(
+                requester.user,
+                identifier,
+            )
+            defer.returnValue((200, ret_dict))
+        else:  # room id
+            msg_handler = self.handlers.message_handler
+            content = {"membership": Membership.JOIN}
+            if requester.is_guest:
+                content["kind"] = "guest"
+            yield msg_handler.create_and_send_event(
+                {
+                    "type": EventTypes.Member,
+                    "content": content,
+                    "room_id": identifier.to_string(),
+                    "sender": requester.user.to_string(),
+                    "state_key": requester.user.to_string(),
+                },
+                token_id=requester.access_token_id,
+                txn_id=txn_id,
+                is_guest=requester.is_guest,
+            )
+
+            defer.returnValue((200, {"room_id": identifier.to_string()}))
+
+    @defer.inlineCallbacks
+    def on_PUT(self, request, room_identifier, txn_id):
+        try:
+            defer.returnValue(
+                self.txns.get_client_transaction(request, txn_id)
+            )
+        except KeyError:
+            pass
+
+        response = yield self.on_POST(request, room_identifier, txn_id)
+
+        self.txns.store_client_transaction(request, txn_id, response)
+        defer.returnValue(response)
 
 
 # TODO: Needs unit testing
diff --git a/synapse/types.py b/synapse/types.py
index 0be8384e18..2095837ba6 100644
--- a/synapse/types.py
+++ b/synapse/types.py
@@ -13,7 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from synapse.api.errors import SynapseError, BadIdentifierError
+from synapse.api.errors import SynapseError
 
 from collections import namedtuple
 
@@ -51,13 +51,13 @@ class DomainSpecificString(
     def from_string(cls, s):
         """Parse the string given by 's' into a structure object."""
         if len(s) < 1 or s[0] != cls.SIGIL:
-            raise BadIdentifierError(400, "Expected %s string to start with '%s'" % (
+            raise SynapseError(400, "Expected %s string to start with '%s'" % (
                 cls.__name__, cls.SIGIL,
             ))
 
         parts = s[1:].split(':', 1)
         if len(parts) != 2:
-            raise BadIdentifierError(
+            raise SynapseError(
                 400, "Expected %s of the form '%slocalname:domain'" % (
                     cls.__name__, cls.SIGIL,
                 )
@@ -69,14 +69,6 @@ class DomainSpecificString(
         # names on one HS
         return cls(localpart=parts[0], domain=domain)
 
-    @classmethod
-    def is_valid(cls, s):
-        try:
-            cls.from_string(s)
-            return True
-        except:
-            return False
-
     def to_string(self):
         """Return a string encoding the fields of the structure object."""
         return "%s%s:%s" % (self.SIGIL, self.localpart, self.domain)