summary refs log tree commit diff
path: root/synapse
diff options
context:
space:
mode:
authorKegan Dougal <kegan@matrix.org>2014-08-27 09:43:42 +0100
committerKegan Dougal <kegan@matrix.org>2014-08-27 09:43:42 +0100
commitdfa0cd1d90cb80de7e42fc2c8aaac8911287d718 (patch)
treeeac44e8ff4b18b5649d4f46adcfd25c562b7fb9e /synapse
parentPepper UT TODOs (diff)
downloadsynapse-dfa0cd1d90cb80de7e42fc2c8aaac8911287d718.tar.xz
Modified /join/$identifier to support $identifier being a room ID in addition to a room alias.
Diffstat (limited to '')
-rw-r--r--synapse/api/auth.py2
-rw-r--r--synapse/rest/room.py63
-rw-r--r--synapse/server.py10
3 files changed, 61 insertions, 14 deletions
diff --git a/synapse/api/auth.py b/synapse/api/auth.py
index 15407df14a..886e132e10 100644
--- a/synapse/api/auth.py
+++ b/synapse/api/auth.py
@@ -162,6 +162,8 @@ class Auth(object):
         """
         try:
             user_id = yield self.store.get_user_by_token(token=token)
+            if not user_id:
+                raise StoreError()
             defer.returnValue(self.hs.parse_userid(user_id))
         except StoreError:
             raise AuthError(403, "Unrecognised access token.",
diff --git a/synapse/rest/room.py b/synapse/rest/room.py
index 5eee49e513..b8d5cb87fd 100644
--- a/synapse/rest/room.py
+++ b/synapse/rest/room.py
@@ -18,10 +18,8 @@ from twisted.internet import defer
 
 from base import RestServlet, client_path_pattern
 from synapse.api.errors import SynapseError, Codes
-from synapse.api.events.room import (
-    MessageEvent, RoomMemberEvent, FeedbackEvent
-)
-from synapse.api.constants import Feedback
+from synapse.api.events.room import RoomMemberEvent
+from synapse.api.constants import Membership
 from synapse.api.streams import PaginationConfig
 
 import json
@@ -210,24 +208,63 @@ class RoomSendEventRestServlet(RestServlet):
         defer.returnValue(response)
 
 
+# TODO: Needs unit testing for room ID + alias joins
 class JoinRoomAliasServlet(RestServlet):
-    PATTERN = client_path_pattern("/join/(?P<room_alias>[^/]+)$")
+
+    def register(self, http_server):
+        # /join/$room_identifier[/$txn_id]
+        PATTERN = ("/join/(?P<room_identifier>[^/]*)")
+        register_txn_path(self, PATTERN, http_server)
 
     @defer.inlineCallbacks
-    def on_PUT(self, request, room_alias):
+    def on_POST(self, request, room_identifier):
         user = yield self.auth.get_user_by_req(request)
 
-        if not user:
-            defer.returnValue((403, "Unrecognized user"))
+        # 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.
 
-        logger.debug("room_alias: %s", room_alias)
+        identifier = None
+        is_room_alias = False
+        try:
+            identifier = self.hs.parse_roomalias(
+                urllib.unquote(room_identifier)
+            )
+            is_room_alias = True
+        except SynapseError:
+            identifier = self.hs.parse_roomid(
+                urllib.unquote(room_identifier)
+            )
 
-        room_alias = self.hs.parse_roomalias(urllib.unquote(room_alias))
+        # TODO: Support for specifying the home server to join with?
 
-        handler = self.handlers.room_member_handler
-        ret_dict = yield handler.join_room_alias(user, room_alias)
+        if is_room_alias:
+            handler = self.handlers.room_member_handler
+            ret_dict = yield handler.join_room_alias(user, identifier)
+            defer.returnValue((200, ret_dict))
+        else:  # room id
+            event = self.event_factory.create_event(
+                etype=RoomMemberEvent.TYPE,
+                content={"membership": Membership.JOIN},
+                room_id=urllib.unquote(identifier.to_string()),
+                user_id=user.to_string(),
+                state_key=user.to_string()
+            )
+            handler = self.handlers.room_member_handler
+            yield handler.change_membership(event)
+            defer.returnValue((200, ""))
+
+    @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)
 
-        defer.returnValue((200, ret_dict))
+        self.txns.store_client_transaction(request, txn_id, response)
+        defer.returnValue(response)
 
 
 # TODO: Needs unit testing
diff --git a/synapse/server.py b/synapse/server.py
index c5b0a32757..439b9d628e 100644
--- a/synapse/server.py
+++ b/synapse/server.py
@@ -28,7 +28,7 @@ from synapse.handlers import Handlers
 from synapse.rest import RestServletFactory
 from synapse.state import StateHandler
 from synapse.storage import DataStore
-from synapse.types import UserID, RoomAlias
+from synapse.types import UserID, RoomAlias, RoomID
 from synapse.util import Clock
 from synapse.util.distributor import Distributor
 from synapse.util.lockutils import LockManager
@@ -117,6 +117,9 @@ class BaseHomeServer(object):
 
         setattr(BaseHomeServer, "get_%s" % (depname), _get)
 
+    # TODO: Why are these parse_ methods so high up along with other globals?
+    # Surely these should be in a util package or in the api package?
+
     # Other utility methods
     def parse_userid(self, s):
         """Parse the string given by 's' as a User ID and return a UserID
@@ -128,6 +131,11 @@ class BaseHomeServer(object):
         object."""
         return RoomAlias.from_string(s, hs=self)
 
+    def parse_roomid(self, s):
+        """Parse the string given by 's' as a Room ID and return a RoomID
+        object."""
+        return RoomID.from_string(s, hs=self)
+
 # Build magic accessors for every dependency
 for depname in BaseHomeServer.DEPENDENCIES:
     BaseHomeServer._make_dependency_method(depname)