diff --git a/synapse/rest/room.py b/synapse/rest/room.py
deleted file mode 100644
index 48bba2a5f3..0000000000
--- a/synapse/rest/room.py
+++ /dev/null
@@ -1,559 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright 2014, 2015 OpenMarket Ltd
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-""" This module contains REST servlets to do with rooms: /rooms/<paths> """
-from twisted.internet import defer
-
-from base import RestServlet, client_path_pattern
-from synapse.api.errors import SynapseError, Codes
-from synapse.streams.config import PaginationConfig
-from synapse.api.constants import EventTypes, Membership
-
-import json
-import logging
-import urllib
-
-
-logger = logging.getLogger(__name__)
-
-
-class RoomCreateRestServlet(RestServlet):
- # No PATTERN; we have custom dispatch rules here
-
- def register(self, http_server):
- PATTERN = "/createRoom"
- register_txn_path(self, PATTERN, http_server)
- # define CORS for all of /rooms in RoomCreateRestServlet for simplicity
- http_server.register_path("OPTIONS",
- client_path_pattern("/rooms(?:/.*)?$"),
- self.on_OPTIONS)
- # define CORS for /createRoom[/txnid]
- http_server.register_path("OPTIONS",
- client_path_pattern("/createRoom(?:/.*)?$"),
- self.on_OPTIONS)
-
- @defer.inlineCallbacks
- def on_PUT(self, request, txn_id):
- try:
- defer.returnValue(
- self.txns.get_client_transaction(request, txn_id)
- )
- except KeyError:
- pass
-
- response = yield self.on_POST(request)
-
- self.txns.store_client_transaction(request, txn_id, response)
- defer.returnValue(response)
-
- @defer.inlineCallbacks
- def on_POST(self, request):
- auth_user = yield self.auth.get_user_by_req(request)
-
- room_config = self.get_room_config(request)
- info = yield self.make_room(room_config, auth_user, None)
- room_config.update(info)
- defer.returnValue((200, info))
-
- @defer.inlineCallbacks
- def make_room(self, room_config, auth_user, room_id):
- handler = self.handlers.room_creation_handler
- info = yield handler.create_room(
- user_id=auth_user.to_string(),
- room_id=room_id,
- config=room_config
- )
- defer.returnValue(info)
-
- def get_room_config(self, request):
- try:
- user_supplied_config = json.loads(request.content.read())
- if "visibility" not in user_supplied_config:
- # default visibility
- user_supplied_config["visibility"] = "public"
- return user_supplied_config
- except (ValueError, TypeError):
- raise SynapseError(400, "Body must be JSON.",
- errcode=Codes.BAD_JSON)
-
- def on_OPTIONS(self, request):
- return (200, {})
-
-
-# TODO: Needs unit testing for generic events
-class RoomStateEventRestServlet(RestServlet):
- def register(self, http_server):
- # /room/$roomid/state/$eventtype
- no_state_key = "/rooms/(?P<room_id>[^/]*)/state/(?P<event_type>[^/]*)$"
-
- # /room/$roomid/state/$eventtype/$statekey
- state_key = ("/rooms/(?P<room_id>[^/]*)/state/"
- "(?P<event_type>[^/]*)/(?P<state_key>[^/]*)$")
-
- http_server.register_path("GET",
- client_path_pattern(state_key),
- self.on_GET)
- http_server.register_path("PUT",
- client_path_pattern(state_key),
- self.on_PUT)
- http_server.register_path("GET",
- client_path_pattern(no_state_key),
- self.on_GET_no_state_key)
- http_server.register_path("PUT",
- client_path_pattern(no_state_key),
- self.on_PUT_no_state_key)
-
- def on_GET_no_state_key(self, request, room_id, event_type):
- return self.on_GET(request, room_id, event_type, "")
-
- def on_PUT_no_state_key(self, request, room_id, event_type):
- return self.on_PUT(request, room_id, event_type, "")
-
- @defer.inlineCallbacks
- def on_GET(self, request, room_id, event_type, state_key):
- user = yield self.auth.get_user_by_req(request)
-
- msg_handler = self.handlers.message_handler
- data = yield msg_handler.get_room_data(
- user_id=user.to_string(),
- room_id=room_id,
- event_type=event_type,
- state_key=state_key,
- )
-
- if not data:
- raise SynapseError(
- 404, "Event not found.", errcode=Codes.NOT_FOUND
- )
- defer.returnValue((200, data.get_dict()["content"]))
-
- @defer.inlineCallbacks
- def on_PUT(self, request, room_id, event_type, state_key):
- user = yield self.auth.get_user_by_req(request)
-
- content = _parse_json(request)
-
- event_dict = {
- "type": event_type,
- "content": content,
- "room_id": room_id,
- "sender": user.to_string(),
- }
-
- if state_key is not None:
- event_dict["state_key"] = state_key
-
- msg_handler = self.handlers.message_handler
- yield msg_handler.create_and_send_event(event_dict)
-
- defer.returnValue((200, {}))
-
-
-# TODO: Needs unit testing for generic events + feedback
-class RoomSendEventRestServlet(RestServlet):
-
- def register(self, http_server):
- # /rooms/$roomid/send/$event_type[/$txn_id]
- PATTERN = ("/rooms/(?P<room_id>[^/]*)/send/(?P<event_type>[^/]*)")
- register_txn_path(self, PATTERN, http_server, with_get=True)
-
- @defer.inlineCallbacks
- def on_POST(self, request, room_id, event_type):
- user = yield self.auth.get_user_by_req(request)
- content = _parse_json(request)
-
- msg_handler = self.handlers.message_handler
- event = yield msg_handler.create_and_send_event(
- {
- "type": event_type,
- "content": content,
- "room_id": room_id,
- "sender": user.to_string(),
- }
- )
-
- defer.returnValue((200, {"event_id": event.event_id}))
-
- def on_GET(self, request, room_id, event_type, txn_id):
- return (200, "Not implemented")
-
- @defer.inlineCallbacks
- def on_PUT(self, request, room_id, event_type, txn_id):
- try:
- defer.returnValue(
- self.txns.get_client_transaction(request, txn_id)
- )
- except KeyError:
- pass
-
- response = yield self.on_POST(request, room_id, event_type)
-
- self.txns.store_client_transaction(request, txn_id, response)
- defer.returnValue(response)
-
-
-# TODO: Needs unit testing for room ID + alias joins
-class JoinRoomAliasServlet(RestServlet):
-
- 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_POST(self, request, room_identifier):
- user = yield self.auth.get_user_by_req(request)
-
- # 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.
-
- identifier = None
- is_room_alias = False
- try:
- identifier = self.hs.parse_roomalias(room_identifier)
- is_room_alias = True
- except SynapseError:
- identifier = self.hs.parse_roomid(room_identifier)
-
- # TODO: Support for specifying the home server to join with?
-
- 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
- msg_handler = self.handlers.message_handler
- yield msg_handler.create_and_send_event(
- {
- "type": EventTypes.Member,
- "content": {"membership": Membership.JOIN},
- "room_id": identifier.to_string(),
- "sender": user.to_string(),
- "state_key": user.to_string(),
- }
- )
-
- 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)
-
- self.txns.store_client_transaction(request, txn_id, response)
- defer.returnValue(response)
-
-
-# TODO: Needs unit testing
-class PublicRoomListRestServlet(RestServlet):
- PATTERN = client_path_pattern("/publicRooms$")
-
- @defer.inlineCallbacks
- def on_GET(self, request):
- handler = self.handlers.room_list_handler
- data = yield handler.get_public_room_list()
- defer.returnValue((200, data))
-
-
-# TODO: Needs unit testing
-class RoomMemberListRestServlet(RestServlet):
- PATTERN = client_path_pattern("/rooms/(?P<room_id>[^/]*)/members$")
-
- @defer.inlineCallbacks
- def on_GET(self, request, room_id):
- # TODO support Pagination stream API (limit/tokens)
- user = yield self.auth.get_user_by_req(request)
- handler = self.handlers.room_member_handler
- members = yield handler.get_room_members_as_pagination_chunk(
- room_id=room_id,
- user_id=user.to_string())
-
- for event in members["chunk"]:
- # FIXME: should probably be state_key here, not user_id
- target_user = self.hs.parse_userid(event["user_id"])
- # Presence is an optional cache; don't fail if we can't fetch it
- try:
- presence_handler = self.handlers.presence_handler
- presence_state = yield presence_handler.get_state(
- target_user=target_user, auth_user=user
- )
- event["content"].update(presence_state)
- except:
- pass
-
- defer.returnValue((200, members))
-
-
-# TODO: Needs unit testing
-class RoomMessageListRestServlet(RestServlet):
- PATTERN = client_path_pattern("/rooms/(?P<room_id>[^/]*)/messages$")
-
- @defer.inlineCallbacks
- def on_GET(self, request, room_id):
- user = yield self.auth.get_user_by_req(request)
- pagination_config = PaginationConfig.from_request(
- request, default_limit=10,
- )
- with_feedback = "feedback" in request.args
- as_client_event = "raw" not in request.args
- handler = self.handlers.message_handler
- msgs = yield handler.get_messages(
- room_id=room_id,
- user_id=user.to_string(),
- pagin_config=pagination_config,
- feedback=with_feedback,
- as_client_event=as_client_event
- )
-
- defer.returnValue((200, msgs))
-
-
-# TODO: Needs unit testing
-class RoomStateRestServlet(RestServlet):
- PATTERN = client_path_pattern("/rooms/(?P<room_id>[^/]*)/state$")
-
- @defer.inlineCallbacks
- def on_GET(self, request, room_id):
- user = yield self.auth.get_user_by_req(request)
- handler = self.handlers.message_handler
- # Get all the current state for this room
- events = yield handler.get_state_events(
- room_id=room_id,
- user_id=user.to_string(),
- )
- defer.returnValue((200, events))
-
-
-# TODO: Needs unit testing
-class RoomInitialSyncRestServlet(RestServlet):
- PATTERN = client_path_pattern("/rooms/(?P<room_id>[^/]*)/initialSync$")
-
- @defer.inlineCallbacks
- def on_GET(self, request, room_id):
- user = yield self.auth.get_user_by_req(request)
- pagination_config = PaginationConfig.from_request(request)
- content = yield self.handlers.message_handler.room_initial_sync(
- room_id=room_id,
- user_id=user.to_string(),
- pagin_config=pagination_config,
- )
- defer.returnValue((200, content))
-
-
-class RoomTriggerBackfill(RestServlet):
- PATTERN = client_path_pattern("/rooms/(?P<room_id>[^/]*)/backfill$")
-
- @defer.inlineCallbacks
- def on_GET(self, request, room_id):
- remote_server = urllib.unquote(
- request.args["remote"][0]
- ).decode("UTF-8")
-
- limit = int(request.args["limit"][0])
-
- handler = self.handlers.federation_handler
- events = yield handler.backfill(remote_server, room_id, limit)
-
- res = [self.hs.serialize_event(event) for event in events]
- defer.returnValue((200, res))
-
-
-# TODO: Needs unit testing
-class RoomMembershipRestServlet(RestServlet):
-
- def register(self, http_server):
- # /rooms/$roomid/[invite|join|leave]
- PATTERN = ("/rooms/(?P<room_id>[^/]*)/"
- "(?P<membership_action>join|invite|leave|ban|kick)")
- register_txn_path(self, PATTERN, http_server)
-
- @defer.inlineCallbacks
- def on_POST(self, request, room_id, membership_action):
- user = yield self.auth.get_user_by_req(request)
-
- content = _parse_json(request)
-
- # target user is you unless it is an invite
- state_key = user.to_string()
- if membership_action in ["invite", "ban", "kick"]:
- if "user_id" not in content:
- raise SynapseError(400, "Missing user_id key.")
- state_key = content["user_id"]
-
- if membership_action == "kick":
- membership_action = "leave"
-
- msg_handler = self.handlers.message_handler
- yield msg_handler.create_and_send_event(
- {
- "type": EventTypes.Member,
- "content": {"membership": unicode(membership_action)},
- "room_id": room_id,
- "sender": user.to_string(),
- "state_key": state_key,
- }
- )
-
- defer.returnValue((200, {}))
-
- @defer.inlineCallbacks
- def on_PUT(self, request, room_id, membership_action, txn_id):
- try:
- defer.returnValue(
- self.txns.get_client_transaction(request, txn_id)
- )
- except KeyError:
- pass
-
- response = yield self.on_POST(request, room_id, membership_action)
-
- self.txns.store_client_transaction(request, txn_id, response)
- defer.returnValue(response)
-
-
-class RoomRedactEventRestServlet(RestServlet):
- def register(self, http_server):
- PATTERN = ("/rooms/(?P<room_id>[^/]*)/redact/(?P<event_id>[^/]*)")
- register_txn_path(self, PATTERN, http_server)
-
- @defer.inlineCallbacks
- def on_POST(self, request, room_id, event_id):
- user = yield self.auth.get_user_by_req(request)
- content = _parse_json(request)
-
- msg_handler = self.handlers.message_handler
- event = yield msg_handler.create_and_send_event(
- {
- "type": EventTypes.Redaction,
- "content": content,
- "room_id": room_id,
- "sender": user.to_string(),
- "redacts": event_id,
- }
- )
-
- defer.returnValue((200, {"event_id": event.event_id}))
-
- @defer.inlineCallbacks
- def on_PUT(self, request, room_id, event_id, txn_id):
- try:
- defer.returnValue(
- self.txns.get_client_transaction(request, txn_id)
- )
- except KeyError:
- pass
-
- response = yield self.on_POST(request, room_id, event_id)
-
- self.txns.store_client_transaction(request, txn_id, response)
- defer.returnValue(response)
-
-
-class RoomTypingRestServlet(RestServlet):
- PATTERN = client_path_pattern(
- "/rooms/(?P<room_id>[^/]*)/typing/(?P<user_id>[^/]*)$"
- )
-
- @defer.inlineCallbacks
- def on_PUT(self, request, room_id, user_id):
- auth_user = yield self.auth.get_user_by_req(request)
-
- room_id = urllib.unquote(room_id)
- target_user = self.hs.parse_userid(urllib.unquote(user_id))
-
- content = _parse_json(request)
-
- typing_handler = self.handlers.typing_notification_handler
-
- if content["typing"]:
- yield typing_handler.started_typing(
- target_user=target_user,
- auth_user=auth_user,
- room_id=room_id,
- timeout=content.get("timeout", 30000),
- )
- else:
- yield typing_handler.stopped_typing(
- target_user=target_user,
- auth_user=auth_user,
- room_id=room_id,
- )
-
- defer.returnValue((200, {}))
-
-
-def _parse_json(request):
- try:
- content = json.loads(request.content.read())
- if type(content) != dict:
- raise SynapseError(400, "Content must be a JSON object.",
- errcode=Codes.NOT_JSON)
- return content
- except ValueError:
- raise SynapseError(400, "Content not JSON.", errcode=Codes.NOT_JSON)
-
-
-def register_txn_path(servlet, regex_string, http_server, with_get=False):
- """Registers a transaction-based path.
-
- This registers two paths:
- PUT regex_string/$txnid
- POST regex_string
-
- Args:
- regex_string (str): The regex string to register. Must NOT have a
- trailing $ as this string will be appended to.
- http_server : The http_server to register paths with.
- with_get: True to also register respective GET paths for the PUTs.
- """
- http_server.register_path(
- "POST",
- client_path_pattern(regex_string + "$"),
- servlet.on_POST
- )
- http_server.register_path(
- "PUT",
- client_path_pattern(regex_string + "/(?P<txn_id>[^/]*)$"),
- servlet.on_PUT
- )
- if with_get:
- http_server.register_path(
- "GET",
- client_path_pattern(regex_string + "/(?P<txn_id>[^/]*)$"),
- servlet.on_GET
- )
-
-
-def register_servlets(hs, http_server):
- RoomStateEventRestServlet(hs).register(http_server)
- RoomCreateRestServlet(hs).register(http_server)
- RoomMemberListRestServlet(hs).register(http_server)
- RoomMessageListRestServlet(hs).register(http_server)
- JoinRoomAliasServlet(hs).register(http_server)
- RoomTriggerBackfill(hs).register(http_server)
- RoomMembershipRestServlet(hs).register(http_server)
- RoomSendEventRestServlet(hs).register(http_server)
- PublicRoomListRestServlet(hs).register(http_server)
- RoomStateRestServlet(hs).register(http_server)
- RoomInitialSyncRestServlet(hs).register(http_server)
- RoomRedactEventRestServlet(hs).register(http_server)
- RoomTypingRestServlet(hs).register(http_server)
|