def test_post_room_visibility_key(self): # POST with visibility config key, expect new room id request, channel = make_request(b"POST", b"/createRoom", b'{"visibility":"private"}') render(request, self.resource, self.clock) self.assertEquals(200, int(channel.result["code"])) self.assertTrue("room_id" in channel.json_body)
def test_POST_user_valid(self): user_id = "@kermit:muppet" token = "kermits_access_token" device_id = "frogfone" request_data = json.dumps({ "username": "******", "password": "******", "device_id": device_id }) self.registration_handler.check_username = Mock(return_value=True) self.auth_result = (None, { "username": "******", "password": "******" }, None) self.registration_handler.register = Mock(return_value=(user_id, None)) self.auth_handler.get_access_token_for_user_id = Mock( return_value=token) self.device_handler.check_device_registered = Mock( return_value=device_id) request, channel = make_request(b"POST", self.url, request_data) render(request, self.resource, self.clock) det_data = { "user_id": user_id, "access_token": token, "home_server": self.hs.hostname, "device_id": device_id, } self.assertEquals(channel.result["code"], b"200", channel.result) self.assertDictContainsSubset(det_data, channel.json_body) self.auth_handler.get_login_tuple_for_user_id( user_id, device_id=device_id, initial_device_display_name=None)
def test_POST_createuser_with_valid_user(self): res = JsonResource(self.hs) register_servlets(self.hs, res) request_data = json.dumps( { "localpart": "someone", "displayname": "someone interesting", "duration_seconds": 200, } ) url = b'/_matrix/client/api/v1/createUser?access_token=i_am_an_app_service' user_id = "@someone:interesting" token = "my token" self.registration_handler.get_or_create_user = Mock( return_value=(user_id, token) ) request, channel = make_request(self.reactor, b"POST", url, request_data) render(request, res, self.reactor) self.assertEquals(channel.result["code"], b"200") det_data = { "user_id": user_id, "access_token": token, "home_server": self.hs.hostname, } self.assertDictContainsSubset(det_data, json.loads(channel.result["body"]))
def setUp(self): super(RoomPermissionsTestCase, self).setUp() self.helper.auth_user_id = self.rmcreator_id # create some rooms under the name rmcreator_id self.uncreated_rmid = "!aa:test" self.created_rmid = self.helper.create_room_as(self.rmcreator_id, is_public=False) self.created_public_rmid = self.helper.create_room_as( self.rmcreator_id, is_public=True) # send a message in one of the rooms self.created_rmid_msg_path = ("rooms/%s/send/m.room.message/a1" % (self.created_rmid)).encode('ascii') request, channel = make_request( b"PUT", self.created_rmid_msg_path, b'{"msgtype":"m.text","body":"test msg"}', ) render(request, self.resource, self.clock) self.assertEquals(channel.result["code"], b"200", channel.result) # set topic for public room request, channel = make_request( b"PUT", ("rooms/%s/state/m.room.topic" % self.created_public_rmid).encode('ascii'), b'{"topic":"Public Room Topic"}', ) render(request, self.resource, self.clock) self.assertEquals(channel.result["code"], b"200", channel.result) # auth as user_id now self.helper.auth_user_id = self.user_id
def test_get_member_list_no_permission(self): room_id = self.helper.create_room_as(b"@some_other_guy:red") request, channel = make_request(b"GET", b"/rooms/%s/members" % room_id) render(request, self.resource, self.clock) self.assertEquals(403, int(channel.result["code"]), msg=channel.result["body"])
def test_get_member_list_no_room(self): request, channel = make_request(b"GET", b"/rooms/roomdoesnotexist/members") render(request, self.resource, self.clock) self.assertEquals(403, int(channel.result["code"]), msg=channel.result["body"])
def test_post_room_custom_key(self): # POST with custom config keys, expect new room id request, channel = make_request(b"POST", b"/createRoom", b'{"custom":"stuff"}') render(request, self.resource, self.clock) self.assertEquals(200, int(channel.result["code"])) self.assertTrue("room_id" in channel.json_body)
def test_initial_sync(self): request, channel = make_request(b"GET", "/rooms/%s/initialSync" % self.room_id) render(request, self.resource, self.clock) self.assertEquals(200, int(channel.result["code"])) self.assertEquals(self.room_id, channel.json_body["room_id"]) self.assertEquals("join", channel.json_body["membership"]) # Room state is easier to assert on if we unpack it into a dict state = {} for event in channel.json_body["state"]: if "state_key" not in event: continue t = event["type"] if t not in state: state[t] = [] state[t].append(event) self.assertTrue("m.room.create" in state) self.assertTrue("messages" in channel.json_body) self.assertTrue("chunk" in channel.json_body["messages"]) self.assertTrue("end" in channel.json_body["messages"]) self.assertTrue("presence" in channel.json_body) presence_by_user = { e["content"]["user_id"]: e for e in channel.json_body["presence"] } self.assertTrue(self.user_id in presence_by_user) self.assertEquals("m.presence", presence_by_user[self.user_id]["type"])
def test_get_member_list(self): room_id = self.helper.create_room_as(self.user_id) request, channel = make_request(b"GET", b"/rooms/%s/members" % room_id) render(request, self.resource, self.clock) self.assertEquals(200, int(channel.result["code"]), msg=channel.result["body"])
def change_membership(self, room, src, targ, membership, tok=None, expect_code=200): temp_id = self.auth_user_id self.auth_user_id = src path = "/_matrix/client/r0/rooms/%s/state/m.room.member/%s" % (room, targ) if tok: path = path + "?access_token=%s" % tok data = {"membership": membership} request, channel = make_request("PUT", path, json.dumps(data).encode('utf8')) render(request, self.resource, self.hs.get_reactor()) assert int(channel.result["code"]) == expect_code, ( "Expected: %d, got: %d, resp: %r" % (expect_code, int(channel.result["code"]), channel.result["body"])) self.auth_user_id = temp_id
def test_POST_bad_password(self): request_data = json.dumps({"username": "******", "password": 666}) request, channel = make_request(b"POST", self.url, request_data) render(request, self.resource, self.clock) self.assertEquals(channel.result["code"], b"400", channel.result) self.assertEquals(channel.json_body["error"], "Invalid password")
def create_room_as( self, room_creator=None, is_public=True, tok=None, expect_code=200, ): temp_id = self.auth_user_id self.auth_user_id = room_creator path = "/_matrix/client/r0/createRoom" content = {} if not is_public: content["visibility"] = "private" if tok: path = path + "?access_token=%s" % tok request, channel = make_request(self.hs.get_reactor(), "POST", path, json.dumps(content).encode("utf8")) render(request, self.resource, self.hs.get_reactor()) assert channel.result["code"] == b"%d" % expect_code, channel.result self.auth_user_id = temp_id if expect_code == 200: return channel.json_body["room_id"]
def _make_request(self, method, path): """Create a request from the method/path and return a channel with the response.""" request, channel = make_request(self.reactor, method, path, shorthand=False) request.prepath = [] # This doesn't get set properly by make_request. # Create a site and query for the resource. site = SynapseSite( "test", "site_tag", parse_listener_def({ "type": "http", "port": 0 }), self.resource, "1.0", ) request.site = site resource = site.getResourceFor(request) # Finally, render the resource and return the channel. render(request, resource, self.reactor) return channel
def test_post_room_no_keys(self): # POST with no config keys, expect new room id request, channel = make_request(b"POST", b"/createRoom", b"{}") render(request, self.resource, self.clock) self.assertEquals(200, int(channel.result["code"]), channel.result) self.assertTrue("room_id" in channel.json_body)
def test_register_incorrect_nonce(self): """ Only the provided nonce can be used, as it's checked in the MAC. """ request, channel = make_request("GET", self.url) render(request, self.resource, self.clock) nonce = channel.json_body["nonce"] want_mac = hmac.new(key=b"shared", digestmod=hashlib.sha1) want_mac.update(b"notthenonce\x00bob\x00abc123\x00admin") want_mac = want_mac.hexdigest() body = json.dumps({ "nonce": nonce, "username": "******", "password": "******", "admin": True, "mac": want_mac, }) request, channel = make_request("POST", self.url, body.encode('utf8')) render(request, self.resource, self.clock) self.assertEqual(403, int(channel.result["code"]), msg=channel.result["body"]) self.assertEqual("HMAC incorrect", channel.json_body["error"])
def test_register_correct_nonce(self): """ When the correct nonce is provided, and the right key is provided, the user is registered. """ request, channel = make_request("GET", self.url) render(request, self.resource, self.clock) nonce = channel.json_body["nonce"] want_mac = hmac.new(key=b"shared", digestmod=hashlib.sha1) want_mac.update(nonce.encode('ascii') + b"\x00bob\x00abc123\x00admin") want_mac = want_mac.hexdigest() body = json.dumps({ "nonce": nonce, "username": "******", "password": "******", "admin": True, "mac": want_mac, }) request, channel = make_request("POST", self.url, body.encode('utf8')) render(request, self.resource, self.clock) self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"]) self.assertEqual("@bob:test", channel.json_body["user_id"])
def test_POST_createuser_with_valid_user(self): res = JsonResource(self.hs) register_servlets(self.hs, res) request_data = json.dumps({ "localpart": "someone", "displayname": "someone interesting", "duration_seconds": 200, }) url = b'/_matrix/client/api/v1/createUser?access_token=i_am_an_app_service' user_id = "@someone:interesting" token = "my token" self.registration_handler.get_or_create_user = Mock( return_value=(user_id, token)) request, channel = make_request(b"POST", url, request_data) render(request, res, self.clock) self.assertEquals(channel.result["code"], b"200") det_data = { "user_id": user_id, "access_token": token, "home_server": self.hs.hostname, } self.assertDictContainsSubset(det_data, json.loads(channel.result["body"]))
def test_handler_for_request(self): """ JsonResource.handler_for_request gives correctly decoded URL args to the callback, while Twisted will give the raw bytes of URL query arguments. """ got_kwargs = {} def _callback(request, **kwargs): got_kwargs.update(kwargs) return 200, kwargs res = JsonResource(self.homeserver) res.register_paths( "GET", [re.compile("^/_matrix/foo/(?P<room_id>[^/]*)$")], _callback, "test_servlet", ) request, channel = make_request(self.reactor, b"GET", b"/_matrix/foo/%E2%98%83?a=%E2%98%83") render(request, res, self.reactor) self.assertEqual(request.args, {b"a": ["\N{SNOWMAN}".encode("utf8")]}) self.assertEqual(got_kwargs, {"room_id": "\N{SNOWMAN}"})
def test_render_public_consent(self): """You can observe the terms form without specifying a user""" resource = consent_resource.ConsentResource(self.hs) request, channel = self.make_request("GET", "/consent?v=1", shorthand=False) render(request, resource, self.reactor) self.assertEqual(channel.code, 200)
def test_get_filter_non_existant(self): request, channel = make_request( "GET", "/_matrix/client/r0/user/%s/filter/12382148321" % (self.USER_ID)) render(request, self.resource, self.clock) self.assertEqual(channel.result["code"], b"400") self.assertEquals(channel.json_body["errcode"], Codes.NOT_FOUND)
def test_post_room_known_and_unknown_keys(self): # POST with custom + known config keys, expect new room id request, channel = make_request( b"POST", b"/createRoom", b'{"visibility":"private","custom":"things"}') render(request, self.resource, self.clock) self.assertEquals(200, int(channel.result["code"])) self.assertTrue("room_id" in channel.json_body)
def render(self, request): """ Render a request against the resources registered by the test class's servlets. Args: request (synapse.http.site.SynapseRequest): The request to render. """ render(request, self.resource, self.reactor)
def test_POST_appservice_registration_invalid(self): self.appservice = None # no application service exists request_data = json.dumps({"username": "******"}) request, channel = make_request( b"POST", self.url + b"?access_token=i_am_an_app_service", request_data) render(request, self.resource, self.clock) self.assertEquals(channel.result["code"], b"401", channel.result)
def test_post_room_invalid_content(self): # POST with invalid content / paths, expect 400 request, channel = make_request(b"POST", b"/createRoom", b'{"visibili') render(request, self.resource, self.clock) self.assertEquals(400, int(channel.result["code"])) request, channel = make_request(b"POST", b"/createRoom", b'["hello"]') render(request, self.resource, self.clock) self.assertEquals(400, int(channel.result["code"]))
def do_sync_for_user(self, token): request, channel = make_request(b"GET", b"/sync", access_token=token) render(request, self.resource, self.reactor) if channel.result["code"] != b"200": raise HttpResponseException( int(channel.result["code"]), channel.result["reason"], channel.result["body"], ).to_synapse_error()
def test_add_filter_for_other_user(self): request, channel = make_request( "POST", "/_matrix/client/r0/user/%s/filter" % ("@watermelon:test"), self.EXAMPLE_FILTER_JSON, ) render(request, self.resource, self.clock) self.assertEqual(channel.result["code"], b"403") self.assertEquals(channel.json_body["errcode"], Codes.FORBIDDEN)
def test_POST_disabled_guest_registration(self): self.hs.config.allow_guest_access = False request, channel = make_request(b"POST", self.url + b"?kind=guest", b"{}") render(request, self.resource, self.clock) self.assertEquals(channel.result["code"], b"403", channel.result) self.assertEquals(channel.json_body["error"], "Guest access is disabled")
def do_sync_for_user(self, token): request, channel = make_request("GET", "/sync", access_token=token.encode('ascii')) render(request, self.resource, self.reactor) if channel.code != 200: raise HttpResponseException( channel.code, channel.result["reason"], channel.result["body"]).to_synapse_error()
def test_stream_token_is_accepted_for_fwd_pagianation(self): token = "s0_0_0_0_0_0_0_0_0" request, channel = make_request( b"GET", "/rooms/%s/messages?access_token=x&from=%s" % (self.room_id, token)) render(request, self.resource, self.clock) self.assertEquals(200, int(channel.result["code"])) self.assertTrue("start" in channel.json_body) self.assertEquals(token, channel.json_body['start']) self.assertTrue("chunk" in channel.json_body) self.assertTrue("end" in channel.json_body)
def test_send_message(self): msg_content = b'{"msgtype":"m.text","body":"hello"}' seq = iter(range(100)) def send_msg_path(): return b"/rooms/%s/send/m.room.message/mid%s" % ( self.created_rmid, str(next(seq)).encode('ascii'), ) # send message in uncreated room, expect 403 request, channel = make_request( b"PUT", b"/rooms/%s/send/m.room.message/mid2" % (self.uncreated_rmid, ), msg_content, ) render(request, self.resource, self.clock) self.assertEquals(403, int(channel.result["code"]), msg=channel.result["body"]) # send message in created room not joined (no state), expect 403 request, channel = make_request(b"PUT", send_msg_path(), msg_content) render(request, self.resource, self.clock) self.assertEquals(403, int(channel.result["code"]), msg=channel.result["body"]) # send message in created room and invited, expect 403 self.helper.invite(room=self.created_rmid, src=self.rmcreator_id, targ=self.user_id) request, channel = make_request(b"PUT", send_msg_path(), msg_content) render(request, self.resource, self.clock) self.assertEquals(403, int(channel.result["code"]), msg=channel.result["body"]) # send message in created room and joined, expect 200 self.helper.join(room=self.created_rmid, user=self.user_id) request, channel = make_request(b"PUT", send_msg_path(), msg_content) render(request, self.resource, self.clock) self.assertEquals(200, int(channel.result["code"]), msg=channel.result["body"]) # send message in created room and left, expect 403 self.helper.leave(room=self.created_rmid, user=self.user_id) request, channel = make_request(b"PUT", send_msg_path(), msg_content) render(request, self.resource, self.clock) self.assertEquals(403, int(channel.result["code"]), msg=channel.result["body"])
def test_get_filter(self): filter_id = self.filtering.add_user_filter( user_localpart="apple", user_filter=self.EXAMPLE_FILTER) self.clock.advance(1) filter_id = filter_id.result request, channel = make_request( "GET", "/_matrix/client/r0/user/%s/filter/%s" % (self.USER_ID, filter_id)) render(request, self.resource, self.clock) self.assertEqual(channel.result["code"], b"200") self.assertEquals(channel.json_body, self.EXAMPLE_FILTER)
def test_callback_direct_exception(self): """ If the web callback raises an uncaught exception, it will be translated into a 500. """ def _callback(request, **kwargs): raise Exception("boo") res = JsonResource(self.homeserver) res.register_paths("GET", [re.compile("^/_matrix/foo$")], _callback) request, channel = make_request(self.reactor, b"GET", b"/_matrix/foo") render(request, res, self.reactor) self.assertEqual(channel.result["code"], b'500')
def test_callback_synapseerror(self): """ If the web callback raises a SynapseError, it returns the appropriate status code and message set in it. """ def _callback(request, **kwargs): raise SynapseError(403, "Forbidden!!one!", Codes.FORBIDDEN) res = JsonResource(self.homeserver) res.register_paths("GET", [re.compile("^/_matrix/foo$")], _callback) request, channel = make_request(self.reactor, b"GET", b"/_matrix/foo") render(request, res, self.reactor) self.assertEqual(channel.result["code"], b'403') self.assertEqual(channel.json_body["error"], "Forbidden!!one!") self.assertEqual(channel.json_body["errcode"], "M_FORBIDDEN")
def create_room_as(self, room_creator, is_public=True, tok=None): temp_id = self.auth_user_id self.auth_user_id = room_creator path = "/_matrix/client/r0/createRoom" content = {} if not is_public: content["visibility"] = "private" if tok: path = path + "?access_token=%s" % tok request, channel = make_request( self.hs.get_reactor(), "POST", path, json.dumps(content).encode('utf8') ) render(request, self.resource, self.hs.get_reactor()) assert channel.result["code"] == b"200", channel.result self.auth_user_id = temp_id return channel.json_body["room_id"]
def test_no_handler(self): """ If there is no handler to process the request, Synapse will return 400. """ def _callback(request, **kwargs): """ Not ever actually called! """ self.fail("shouldn't ever get here") res = JsonResource(self.homeserver) res.register_paths("GET", [re.compile("^/_matrix/foo$")], _callback) request, channel = make_request(self.reactor, b"GET", b"/_matrix/foobar") render(request, res, self.reactor) self.assertEqual(channel.result["code"], b'400') self.assertEqual(channel.json_body["error"], "Unrecognized request") self.assertEqual(channel.json_body["errcode"], "M_UNRECOGNIZED")
def test_callback_indirect_exception(self): """ If the web callback raises an uncaught exception in a Deferred, it will be translated into a 500. """ def _throw(*args): raise Exception("boo") def _callback(request, **kwargs): d = Deferred() d.addCallback(_throw) self.reactor.callLater(1, d.callback, True) return make_deferred_yieldable(d) res = JsonResource(self.homeserver) res.register_paths("GET", [re.compile("^/_matrix/foo$")], _callback) request, channel = make_request(self.reactor, b"GET", b"/_matrix/foo") render(request, res, self.reactor) self.assertEqual(channel.result["code"], b'500')
def send(self, room_id, body=None, txn_id=None, tok=None, expect_code=200): if txn_id is None: txn_id = "m%s" % (str(time.time())) if body is None: body = "body_text_here" path = "/_matrix/client/r0/rooms/%s/send/m.room.message/%s" % (room_id, txn_id) content = {"msgtype": "m.text", "body": body} if tok: path = path + "?access_token=%s" % tok request, channel = make_request( self.hs.get_reactor(), "PUT", path, json.dumps(content).encode('utf8') ) render(request, self.resource, self.hs.get_reactor()) assert int(channel.result["code"]) == expect_code, ( "Expected: %d, got: %d, resp: %r" % (expect_code, int(channel.result["code"]), channel.result["body"]) ) return channel.json_body
def change_membership(self, room, src, targ, membership, tok=None, expect_code=200): temp_id = self.auth_user_id self.auth_user_id = src path = "/_matrix/client/r0/rooms/%s/state/m.room.member/%s" % (room, targ) if tok: path = path + "?access_token=%s" % tok data = {"membership": membership} request, channel = make_request( self.hs.get_reactor(), "PUT", path, json.dumps(data).encode('utf8') ) render(request, self.resource, self.hs.get_reactor()) assert int(channel.result["code"]) == expect_code, ( "Expected: %d, got: %d, resp: %r" % (expect_code, int(channel.result["code"]), channel.result["body"]) ) self.auth_user_id = temp_id
def test_handler_for_request(self): """ JsonResource.handler_for_request gives correctly decoded URL args to the callback, while Twisted will give the raw bytes of URL query arguments. """ got_kwargs = {} def _callback(request, **kwargs): got_kwargs.update(kwargs) return (200, kwargs) res = JsonResource(self.homeserver) res.register_paths( "GET", [re.compile("^/_matrix/foo/(?P<room_id>[^/]*)$")], _callback ) request, channel = make_request( self.reactor, b"GET", b"/_matrix/foo/%E2%98%83?a=%E2%98%83" ) render(request, res, self.reactor) self.assertEqual(request.args, {b'a': [u"\N{SNOWMAN}".encode('utf8')]}) self.assertEqual(got_kwargs, {u"room_id": u"\N{SNOWMAN}"})
def test_accept_consent(self): """ A user can use the consent form to accept the terms. """ uri_builder = ConsentURIBuilder(self.hs.config) resource = consent_resource.ConsentResource(self.hs) # Register a user user_id = self.register_user("user", "pass") access_token = self.login("user", "pass") # Fetch the consent page, to get the consent version consent_uri = ( uri_builder.build_user_consent_uri(user_id).replace("_matrix/", "") + "&u=user" ) request, channel = self.make_request( "GET", consent_uri, access_token=access_token, shorthand=False ) render(request, resource, self.reactor) self.assertEqual(channel.code, 200) # Get the version from the body, and whether we've consented version, consented = channel.result["body"].decode('ascii').split(",") self.assertEqual(consented, "False") # POST to the consent page, saying we've agreed request, channel = self.make_request( "POST", consent_uri + "&v=" + version, access_token=access_token, shorthand=False, ) render(request, resource, self.reactor) self.assertEqual(channel.code, 200) # Fetch the consent page, to get the consent version -- it should have # changed request, channel = self.make_request( "GET", consent_uri, access_token=access_token, shorthand=False ) render(request, resource, self.reactor) self.assertEqual(channel.code, 200) # Get the version from the body, and check that it's the version we # agreed to, and that we've consented to it. version, consented = channel.result["body"].decode('ascii').split(",") self.assertEqual(consented, "True") self.assertEqual(version, "1")