test_rooms.py 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2014-2016 OpenMarket Ltd
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. """Tests REST events for /rooms paths."""
  16. # twisted imports
  17. from twisted.internet import defer
  18. import synapse.rest.client.v1.room
  19. from synapse.api.constants import Membership
  20. from synapse.types import UserID
  21. import json
  22. import urllib
  23. from ....utils import MockHttpResource, setup_test_homeserver
  24. from .utils import RestTestCase
  25. from mock import Mock, NonCallableMock
  26. PATH_PREFIX = "/_matrix/client/api/v1"
  27. class RoomPermissionsTestCase(RestTestCase):
  28. """ Tests room permissions. """
  29. user_id = "@sid1:red"
  30. rmcreator_id = "@notme:red"
  31. @defer.inlineCallbacks
  32. def setUp(self):
  33. self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
  34. hs = yield setup_test_homeserver(
  35. "red",
  36. http_client=None,
  37. replication_layer=Mock(),
  38. ratelimiter=NonCallableMock(spec_set=["send_message"]),
  39. )
  40. self.ratelimiter = hs.get_ratelimiter()
  41. self.ratelimiter.send_message.return_value = (True, 0)
  42. hs.get_handlers().federation_handler = Mock()
  43. def get_user_by_access_token(token=None, allow_guest=False):
  44. return {
  45. "user": UserID.from_string(self.auth_user_id),
  46. "token_id": 1,
  47. "is_guest": False,
  48. }
  49. hs.get_v1auth().get_user_by_access_token = get_user_by_access_token
  50. def _insert_client_ip(*args, **kwargs):
  51. return defer.succeed(None)
  52. hs.get_datastore().insert_client_ip = _insert_client_ip
  53. self.auth_user_id = self.rmcreator_id
  54. synapse.rest.client.v1.room.register_servlets(hs, self.mock_resource)
  55. self.auth = hs.get_v1auth()
  56. # create some rooms under the name rmcreator_id
  57. self.uncreated_rmid = "!aa:test"
  58. self.created_rmid = yield self.create_room_as(self.rmcreator_id,
  59. is_public=False)
  60. self.created_public_rmid = yield self.create_room_as(self.rmcreator_id,
  61. is_public=True)
  62. # send a message in one of the rooms
  63. self.created_rmid_msg_path = (
  64. "/rooms/%s/send/m.room.message/a1" % (self.created_rmid)
  65. )
  66. (code, response) = yield self.mock_resource.trigger(
  67. "PUT",
  68. self.created_rmid_msg_path,
  69. '{"msgtype":"m.text","body":"test msg"}'
  70. )
  71. self.assertEquals(200, code, msg=str(response))
  72. # set topic for public room
  73. (code, response) = yield self.mock_resource.trigger(
  74. "PUT",
  75. "/rooms/%s/state/m.room.topic" % self.created_public_rmid,
  76. '{"topic":"Public Room Topic"}'
  77. )
  78. self.assertEquals(200, code, msg=str(response))
  79. # auth as user_id now
  80. self.auth_user_id = self.user_id
  81. def tearDown(self):
  82. pass
  83. @defer.inlineCallbacks
  84. def test_send_message(self):
  85. msg_content = '{"msgtype":"m.text","body":"hello"}'
  86. send_msg_path = (
  87. "/rooms/%s/send/m.room.message/mid1" % (self.created_rmid,)
  88. )
  89. # send message in uncreated room, expect 403
  90. (code, response) = yield self.mock_resource.trigger(
  91. "PUT",
  92. "/rooms/%s/send/m.room.message/mid2" % (self.uncreated_rmid,),
  93. msg_content
  94. )
  95. self.assertEquals(403, code, msg=str(response))
  96. # send message in created room not joined (no state), expect 403
  97. (code, response) = yield self.mock_resource.trigger(
  98. "PUT",
  99. send_msg_path,
  100. msg_content
  101. )
  102. self.assertEquals(403, code, msg=str(response))
  103. # send message in created room and invited, expect 403
  104. yield self.invite(
  105. room=self.created_rmid,
  106. src=self.rmcreator_id,
  107. targ=self.user_id
  108. )
  109. (code, response) = yield self.mock_resource.trigger(
  110. "PUT",
  111. send_msg_path,
  112. msg_content
  113. )
  114. self.assertEquals(403, code, msg=str(response))
  115. # send message in created room and joined, expect 200
  116. yield self.join(room=self.created_rmid, user=self.user_id)
  117. (code, response) = yield self.mock_resource.trigger(
  118. "PUT",
  119. send_msg_path,
  120. msg_content
  121. )
  122. self.assertEquals(200, code, msg=str(response))
  123. # send message in created room and left, expect 403
  124. yield self.leave(room=self.created_rmid, user=self.user_id)
  125. (code, response) = yield self.mock_resource.trigger(
  126. "PUT",
  127. send_msg_path,
  128. msg_content
  129. )
  130. self.assertEquals(403, code, msg=str(response))
  131. @defer.inlineCallbacks
  132. def test_topic_perms(self):
  133. topic_content = '{"topic":"My Topic Name"}'
  134. topic_path = "/rooms/%s/state/m.room.topic" % self.created_rmid
  135. # set/get topic in uncreated room, expect 403
  136. (code, response) = yield self.mock_resource.trigger(
  137. "PUT", "/rooms/%s/state/m.room.topic" % self.uncreated_rmid,
  138. topic_content
  139. )
  140. self.assertEquals(403, code, msg=str(response))
  141. (code, response) = yield self.mock_resource.trigger_get(
  142. "/rooms/%s/state/m.room.topic" % self.uncreated_rmid
  143. )
  144. self.assertEquals(403, code, msg=str(response))
  145. # set/get topic in created PRIVATE room not joined, expect 403
  146. (code, response) = yield self.mock_resource.trigger(
  147. "PUT", topic_path, topic_content
  148. )
  149. self.assertEquals(403, code, msg=str(response))
  150. (code, response) = yield self.mock_resource.trigger_get(topic_path)
  151. self.assertEquals(403, code, msg=str(response))
  152. # set topic in created PRIVATE room and invited, expect 403
  153. yield self.invite(
  154. room=self.created_rmid, src=self.rmcreator_id, targ=self.user_id
  155. )
  156. (code, response) = yield self.mock_resource.trigger(
  157. "PUT", topic_path, topic_content
  158. )
  159. self.assertEquals(403, code, msg=str(response))
  160. # get topic in created PRIVATE room and invited, expect 403
  161. (code, response) = yield self.mock_resource.trigger_get(topic_path)
  162. self.assertEquals(403, code, msg=str(response))
  163. # set/get topic in created PRIVATE room and joined, expect 200
  164. yield self.join(room=self.created_rmid, user=self.user_id)
  165. # Only room ops can set topic by default
  166. self.auth_user_id = self.rmcreator_id
  167. (code, response) = yield self.mock_resource.trigger(
  168. "PUT", topic_path, topic_content
  169. )
  170. self.assertEquals(200, code, msg=str(response))
  171. self.auth_user_id = self.user_id
  172. (code, response) = yield self.mock_resource.trigger_get(topic_path)
  173. self.assertEquals(200, code, msg=str(response))
  174. self.assert_dict(json.loads(topic_content), response)
  175. # set/get topic in created PRIVATE room and left, expect 403
  176. yield self.leave(room=self.created_rmid, user=self.user_id)
  177. (code, response) = yield self.mock_resource.trigger(
  178. "PUT", topic_path, topic_content
  179. )
  180. self.assertEquals(403, code, msg=str(response))
  181. (code, response) = yield self.mock_resource.trigger_get(topic_path)
  182. self.assertEquals(200, code, msg=str(response))
  183. # get topic in PUBLIC room, not joined, expect 403
  184. (code, response) = yield self.mock_resource.trigger_get(
  185. "/rooms/%s/state/m.room.topic" % self.created_public_rmid
  186. )
  187. self.assertEquals(403, code, msg=str(response))
  188. # set topic in PUBLIC room, not joined, expect 403
  189. (code, response) = yield self.mock_resource.trigger(
  190. "PUT",
  191. "/rooms/%s/state/m.room.topic" % self.created_public_rmid,
  192. topic_content
  193. )
  194. self.assertEquals(403, code, msg=str(response))
  195. @defer.inlineCallbacks
  196. def _test_get_membership(self, room=None, members=[], expect_code=None):
  197. for member in members:
  198. path = "/rooms/%s/state/m.room.member/%s" % (room, member)
  199. (code, response) = yield self.mock_resource.trigger_get(path)
  200. self.assertEquals(expect_code, code)
  201. @defer.inlineCallbacks
  202. def test_membership_basic_room_perms(self):
  203. # === room does not exist ===
  204. room = self.uncreated_rmid
  205. # get membership of self, get membership of other, uncreated room
  206. # expect all 403s
  207. yield self._test_get_membership(
  208. members=[self.user_id, self.rmcreator_id],
  209. room=room, expect_code=403)
  210. # trying to invite people to this room should 403
  211. yield self.invite(room=room, src=self.user_id, targ=self.rmcreator_id,
  212. expect_code=403)
  213. # set [invite/join/left] of self, set [invite/join/left] of other,
  214. # expect all 404s because room doesn't exist on any server
  215. for usr in [self.user_id, self.rmcreator_id]:
  216. yield self.join(room=room, user=usr, expect_code=403)
  217. yield self.leave(room=room, user=usr, expect_code=403)
  218. @defer.inlineCallbacks
  219. def test_membership_private_room_perms(self):
  220. room = self.created_rmid
  221. # get membership of self, get membership of other, private room + invite
  222. # expect all 403s
  223. yield self.invite(room=room, src=self.rmcreator_id,
  224. targ=self.user_id)
  225. yield self._test_get_membership(
  226. members=[self.user_id, self.rmcreator_id],
  227. room=room, expect_code=403)
  228. # get membership of self, get membership of other, private room + joined
  229. # expect all 200s
  230. yield self.join(room=room, user=self.user_id)
  231. yield self._test_get_membership(
  232. members=[self.user_id, self.rmcreator_id],
  233. room=room, expect_code=200)
  234. # get membership of self, get membership of other, private room + left
  235. # expect all 200s
  236. yield self.leave(room=room, user=self.user_id)
  237. yield self._test_get_membership(
  238. members=[self.user_id, self.rmcreator_id],
  239. room=room, expect_code=200)
  240. @defer.inlineCallbacks
  241. def test_membership_public_room_perms(self):
  242. room = self.created_public_rmid
  243. # get membership of self, get membership of other, public room + invite
  244. # expect 403
  245. yield self.invite(room=room, src=self.rmcreator_id,
  246. targ=self.user_id)
  247. yield self._test_get_membership(
  248. members=[self.user_id, self.rmcreator_id],
  249. room=room, expect_code=403)
  250. # get membership of self, get membership of other, public room + joined
  251. # expect all 200s
  252. yield self.join(room=room, user=self.user_id)
  253. yield self._test_get_membership(
  254. members=[self.user_id, self.rmcreator_id],
  255. room=room, expect_code=200)
  256. # get membership of self, get membership of other, public room + left
  257. # expect 200.
  258. yield self.leave(room=room, user=self.user_id)
  259. yield self._test_get_membership(
  260. members=[self.user_id, self.rmcreator_id],
  261. room=room, expect_code=200)
  262. @defer.inlineCallbacks
  263. def test_invited_permissions(self):
  264. room = self.created_rmid
  265. yield self.invite(room=room, src=self.rmcreator_id, targ=self.user_id)
  266. # set [invite/join/left] of other user, expect 403s
  267. yield self.invite(room=room, src=self.user_id, targ=self.rmcreator_id,
  268. expect_code=403)
  269. yield self.change_membership(room=room, src=self.user_id,
  270. targ=self.rmcreator_id,
  271. membership=Membership.JOIN,
  272. expect_code=403)
  273. yield self.change_membership(room=room, src=self.user_id,
  274. targ=self.rmcreator_id,
  275. membership=Membership.LEAVE,
  276. expect_code=403)
  277. @defer.inlineCallbacks
  278. def test_joined_permissions(self):
  279. room = self.created_rmid
  280. yield self.invite(room=room, src=self.rmcreator_id, targ=self.user_id)
  281. yield self.join(room=room, user=self.user_id)
  282. # set invited of self, expect 403
  283. yield self.invite(room=room, src=self.user_id, targ=self.user_id,
  284. expect_code=403)
  285. # set joined of self, expect 200 (NOOP)
  286. yield self.join(room=room, user=self.user_id)
  287. other = "@burgundy:red"
  288. # set invited of other, expect 200
  289. yield self.invite(room=room, src=self.user_id, targ=other,
  290. expect_code=200)
  291. # set joined of other, expect 403
  292. yield self.change_membership(room=room, src=self.user_id,
  293. targ=other,
  294. membership=Membership.JOIN,
  295. expect_code=403)
  296. # set left of other, expect 403
  297. yield self.change_membership(room=room, src=self.user_id,
  298. targ=other,
  299. membership=Membership.LEAVE,
  300. expect_code=403)
  301. # set left of self, expect 200
  302. yield self.leave(room=room, user=self.user_id)
  303. @defer.inlineCallbacks
  304. def test_leave_permissions(self):
  305. room = self.created_rmid
  306. yield self.invite(room=room, src=self.rmcreator_id, targ=self.user_id)
  307. yield self.join(room=room, user=self.user_id)
  308. yield self.leave(room=room, user=self.user_id)
  309. # set [invite/join/left] of self, set [invite/join/left] of other,
  310. # expect all 403s
  311. for usr in [self.user_id, self.rmcreator_id]:
  312. yield self.change_membership(
  313. room=room,
  314. src=self.user_id,
  315. targ=usr,
  316. membership=Membership.INVITE,
  317. expect_code=403
  318. )
  319. yield self.change_membership(
  320. room=room,
  321. src=self.user_id,
  322. targ=usr,
  323. membership=Membership.JOIN,
  324. expect_code=403
  325. )
  326. # It is always valid to LEAVE if you've already left (currently.)
  327. yield self.change_membership(
  328. room=room,
  329. src=self.user_id,
  330. targ=self.rmcreator_id,
  331. membership=Membership.LEAVE,
  332. expect_code=403
  333. )
  334. class RoomsMemberListTestCase(RestTestCase):
  335. """ Tests /rooms/$room_id/members/list REST events."""
  336. user_id = "@sid1:red"
  337. @defer.inlineCallbacks
  338. def setUp(self):
  339. self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
  340. hs = yield setup_test_homeserver(
  341. "red",
  342. http_client=None,
  343. replication_layer=Mock(),
  344. ratelimiter=NonCallableMock(spec_set=["send_message"]),
  345. )
  346. self.ratelimiter = hs.get_ratelimiter()
  347. self.ratelimiter.send_message.return_value = (True, 0)
  348. hs.get_handlers().federation_handler = Mock()
  349. self.auth_user_id = self.user_id
  350. def get_user_by_access_token(token=None, allow_guest=False):
  351. return {
  352. "user": UserID.from_string(self.auth_user_id),
  353. "token_id": 1,
  354. "is_guest": False,
  355. }
  356. hs.get_v1auth().get_user_by_access_token = get_user_by_access_token
  357. def _insert_client_ip(*args, **kwargs):
  358. return defer.succeed(None)
  359. hs.get_datastore().insert_client_ip = _insert_client_ip
  360. synapse.rest.client.v1.room.register_servlets(hs, self.mock_resource)
  361. def tearDown(self):
  362. pass
  363. @defer.inlineCallbacks
  364. def test_get_member_list(self):
  365. room_id = yield self.create_room_as(self.user_id)
  366. (code, response) = yield self.mock_resource.trigger_get(
  367. "/rooms/%s/members" % room_id
  368. )
  369. self.assertEquals(200, code, msg=str(response))
  370. @defer.inlineCallbacks
  371. def test_get_member_list_no_room(self):
  372. (code, response) = yield self.mock_resource.trigger_get(
  373. "/rooms/roomdoesnotexist/members"
  374. )
  375. self.assertEquals(403, code, msg=str(response))
  376. @defer.inlineCallbacks
  377. def test_get_member_list_no_permission(self):
  378. room_id = yield self.create_room_as("@some_other_guy:red")
  379. (code, response) = yield self.mock_resource.trigger_get(
  380. "/rooms/%s/members" % room_id
  381. )
  382. self.assertEquals(403, code, msg=str(response))
  383. @defer.inlineCallbacks
  384. def test_get_member_list_mixed_memberships(self):
  385. room_creator = "@some_other_guy:red"
  386. room_id = yield self.create_room_as(room_creator)
  387. room_path = "/rooms/%s/members" % room_id
  388. yield self.invite(room=room_id, src=room_creator,
  389. targ=self.user_id)
  390. # can't see list if you're just invited.
  391. (code, response) = yield self.mock_resource.trigger_get(room_path)
  392. self.assertEquals(403, code, msg=str(response))
  393. yield self.join(room=room_id, user=self.user_id)
  394. # can see list now joined
  395. (code, response) = yield self.mock_resource.trigger_get(room_path)
  396. self.assertEquals(200, code, msg=str(response))
  397. yield self.leave(room=room_id, user=self.user_id)
  398. # can see old list once left
  399. (code, response) = yield self.mock_resource.trigger_get(room_path)
  400. self.assertEquals(200, code, msg=str(response))
  401. class RoomsCreateTestCase(RestTestCase):
  402. """ Tests /rooms and /rooms/$room_id REST events. """
  403. user_id = "@sid1:red"
  404. @defer.inlineCallbacks
  405. def setUp(self):
  406. self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
  407. self.auth_user_id = self.user_id
  408. hs = yield setup_test_homeserver(
  409. "red",
  410. http_client=None,
  411. replication_layer=Mock(),
  412. ratelimiter=NonCallableMock(spec_set=["send_message"]),
  413. )
  414. self.ratelimiter = hs.get_ratelimiter()
  415. self.ratelimiter.send_message.return_value = (True, 0)
  416. hs.get_handlers().federation_handler = Mock()
  417. def get_user_by_access_token(token=None, allow_guest=False):
  418. return {
  419. "user": UserID.from_string(self.auth_user_id),
  420. "token_id": 1,
  421. "is_guest": False,
  422. }
  423. hs.get_v1auth().get_user_by_access_token = get_user_by_access_token
  424. def _insert_client_ip(*args, **kwargs):
  425. return defer.succeed(None)
  426. hs.get_datastore().insert_client_ip = _insert_client_ip
  427. synapse.rest.client.v1.room.register_servlets(hs, self.mock_resource)
  428. def tearDown(self):
  429. pass
  430. @defer.inlineCallbacks
  431. def test_post_room_no_keys(self):
  432. # POST with no config keys, expect new room id
  433. (code, response) = yield self.mock_resource.trigger("POST",
  434. "/createRoom",
  435. "{}")
  436. self.assertEquals(200, code, response)
  437. self.assertTrue("room_id" in response)
  438. @defer.inlineCallbacks
  439. def test_post_room_visibility_key(self):
  440. # POST with visibility config key, expect new room id
  441. (code, response) = yield self.mock_resource.trigger(
  442. "POST",
  443. "/createRoom",
  444. '{"visibility":"private"}')
  445. self.assertEquals(200, code)
  446. self.assertTrue("room_id" in response)
  447. @defer.inlineCallbacks
  448. def test_post_room_custom_key(self):
  449. # POST with custom config keys, expect new room id
  450. (code, response) = yield self.mock_resource.trigger(
  451. "POST",
  452. "/createRoom",
  453. '{"custom":"stuff"}')
  454. self.assertEquals(200, code)
  455. self.assertTrue("room_id" in response)
  456. @defer.inlineCallbacks
  457. def test_post_room_known_and_unknown_keys(self):
  458. # POST with custom + known config keys, expect new room id
  459. (code, response) = yield self.mock_resource.trigger(
  460. "POST",
  461. "/createRoom",
  462. '{"visibility":"private","custom":"things"}')
  463. self.assertEquals(200, code)
  464. self.assertTrue("room_id" in response)
  465. @defer.inlineCallbacks
  466. def test_post_room_invalid_content(self):
  467. # POST with invalid content / paths, expect 400
  468. (code, response) = yield self.mock_resource.trigger(
  469. "POST",
  470. "/createRoom",
  471. '{"visibili')
  472. self.assertEquals(400, code)
  473. (code, response) = yield self.mock_resource.trigger(
  474. "POST",
  475. "/createRoom",
  476. '["hello"]')
  477. self.assertEquals(400, code)
  478. class RoomTopicTestCase(RestTestCase):
  479. """ Tests /rooms/$room_id/topic REST events. """
  480. user_id = "@sid1:red"
  481. @defer.inlineCallbacks
  482. def setUp(self):
  483. self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
  484. self.auth_user_id = self.user_id
  485. hs = yield setup_test_homeserver(
  486. "red",
  487. http_client=None,
  488. replication_layer=Mock(),
  489. ratelimiter=NonCallableMock(spec_set=["send_message"]),
  490. )
  491. self.ratelimiter = hs.get_ratelimiter()
  492. self.ratelimiter.send_message.return_value = (True, 0)
  493. hs.get_handlers().federation_handler = Mock()
  494. def get_user_by_access_token(token=None, allow_guest=False):
  495. return {
  496. "user": UserID.from_string(self.auth_user_id),
  497. "token_id": 1,
  498. "is_guest": False,
  499. }
  500. hs.get_v1auth().get_user_by_access_token = get_user_by_access_token
  501. def _insert_client_ip(*args, **kwargs):
  502. return defer.succeed(None)
  503. hs.get_datastore().insert_client_ip = _insert_client_ip
  504. synapse.rest.client.v1.room.register_servlets(hs, self.mock_resource)
  505. # create the room
  506. self.room_id = yield self.create_room_as(self.user_id)
  507. self.path = "/rooms/%s/state/m.room.topic" % (self.room_id,)
  508. def tearDown(self):
  509. pass
  510. @defer.inlineCallbacks
  511. def test_invalid_puts(self):
  512. # missing keys or invalid json
  513. (code, response) = yield self.mock_resource.trigger(
  514. "PUT", self.path, '{}'
  515. )
  516. self.assertEquals(400, code, msg=str(response))
  517. (code, response) = yield self.mock_resource.trigger(
  518. "PUT", self.path, '{"_name":"bob"}'
  519. )
  520. self.assertEquals(400, code, msg=str(response))
  521. (code, response) = yield self.mock_resource.trigger(
  522. "PUT", self.path, '{"nao'
  523. )
  524. self.assertEquals(400, code, msg=str(response))
  525. (code, response) = yield self.mock_resource.trigger(
  526. "PUT", self.path, '[{"_name":"bob"},{"_name":"jill"}]'
  527. )
  528. self.assertEquals(400, code, msg=str(response))
  529. (code, response) = yield self.mock_resource.trigger(
  530. "PUT", self.path, 'text only'
  531. )
  532. self.assertEquals(400, code, msg=str(response))
  533. (code, response) = yield self.mock_resource.trigger(
  534. "PUT", self.path, ''
  535. )
  536. self.assertEquals(400, code, msg=str(response))
  537. # valid key, wrong type
  538. content = '{"topic":["Topic name"]}'
  539. (code, response) = yield self.mock_resource.trigger(
  540. "PUT", self.path, content
  541. )
  542. self.assertEquals(400, code, msg=str(response))
  543. @defer.inlineCallbacks
  544. def test_rooms_topic(self):
  545. # nothing should be there
  546. (code, response) = yield self.mock_resource.trigger_get(self.path)
  547. self.assertEquals(404, code, msg=str(response))
  548. # valid put
  549. content = '{"topic":"Topic name"}'
  550. (code, response) = yield self.mock_resource.trigger(
  551. "PUT", self.path, content
  552. )
  553. self.assertEquals(200, code, msg=str(response))
  554. # valid get
  555. (code, response) = yield self.mock_resource.trigger_get(self.path)
  556. self.assertEquals(200, code, msg=str(response))
  557. self.assert_dict(json.loads(content), response)
  558. @defer.inlineCallbacks
  559. def test_rooms_topic_with_extra_keys(self):
  560. # valid put with extra keys
  561. content = '{"topic":"Seasons","subtopic":"Summer"}'
  562. (code, response) = yield self.mock_resource.trigger(
  563. "PUT", self.path, content
  564. )
  565. self.assertEquals(200, code, msg=str(response))
  566. # valid get
  567. (code, response) = yield self.mock_resource.trigger_get(self.path)
  568. self.assertEquals(200, code, msg=str(response))
  569. self.assert_dict(json.loads(content), response)
  570. class RoomMemberStateTestCase(RestTestCase):
  571. """ Tests /rooms/$room_id/members/$user_id/state REST events. """
  572. user_id = "@sid1:red"
  573. @defer.inlineCallbacks
  574. def setUp(self):
  575. self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
  576. self.auth_user_id = self.user_id
  577. hs = yield setup_test_homeserver(
  578. "red",
  579. http_client=None,
  580. replication_layer=Mock(),
  581. ratelimiter=NonCallableMock(spec_set=["send_message"]),
  582. )
  583. self.ratelimiter = hs.get_ratelimiter()
  584. self.ratelimiter.send_message.return_value = (True, 0)
  585. hs.get_handlers().federation_handler = Mock()
  586. def get_user_by_access_token(token=None, allow_guest=False):
  587. return {
  588. "user": UserID.from_string(self.auth_user_id),
  589. "token_id": 1,
  590. "is_guest": False,
  591. }
  592. hs.get_v1auth().get_user_by_access_token = get_user_by_access_token
  593. def _insert_client_ip(*args, **kwargs):
  594. return defer.succeed(None)
  595. hs.get_datastore().insert_client_ip = _insert_client_ip
  596. synapse.rest.client.v1.room.register_servlets(hs, self.mock_resource)
  597. self.room_id = yield self.create_room_as(self.user_id)
  598. def tearDown(self):
  599. pass
  600. @defer.inlineCallbacks
  601. def test_invalid_puts(self):
  602. path = "/rooms/%s/state/m.room.member/%s" % (self.room_id, self.user_id)
  603. # missing keys or invalid json
  604. (code, response) = yield self.mock_resource.trigger("PUT", path, '{}')
  605. self.assertEquals(400, code, msg=str(response))
  606. (code, response) = yield self.mock_resource.trigger(
  607. "PUT", path, '{"_name":"bob"}'
  608. )
  609. self.assertEquals(400, code, msg=str(response))
  610. (code, response) = yield self.mock_resource.trigger(
  611. "PUT", path, '{"nao'
  612. )
  613. self.assertEquals(400, code, msg=str(response))
  614. (code, response) = yield self.mock_resource.trigger(
  615. "PUT", path, '[{"_name":"bob"},{"_name":"jill"}]'
  616. )
  617. self.assertEquals(400, code, msg=str(response))
  618. (code, response) = yield self.mock_resource.trigger(
  619. "PUT", path, 'text only'
  620. )
  621. self.assertEquals(400, code, msg=str(response))
  622. (code, response) = yield self.mock_resource.trigger(
  623. "PUT", path, ''
  624. )
  625. self.assertEquals(400, code, msg=str(response))
  626. # valid keys, wrong types
  627. content = ('{"membership":["%s","%s","%s"]}' % (
  628. Membership.INVITE, Membership.JOIN, Membership.LEAVE
  629. ))
  630. (code, response) = yield self.mock_resource.trigger("PUT", path, content)
  631. self.assertEquals(400, code, msg=str(response))
  632. @defer.inlineCallbacks
  633. def test_rooms_members_self(self):
  634. path = "/rooms/%s/state/m.room.member/%s" % (
  635. urllib.quote(self.room_id), self.user_id
  636. )
  637. # valid join message (NOOP since we made the room)
  638. content = '{"membership":"%s"}' % Membership.JOIN
  639. (code, response) = yield self.mock_resource.trigger("PUT", path, content)
  640. self.assertEquals(200, code, msg=str(response))
  641. (code, response) = yield self.mock_resource.trigger("GET", path, None)
  642. self.assertEquals(200, code, msg=str(response))
  643. expected_response = {
  644. "membership": Membership.JOIN,
  645. }
  646. self.assertEquals(expected_response, response)
  647. @defer.inlineCallbacks
  648. def test_rooms_members_other(self):
  649. self.other_id = "@zzsid1:red"
  650. path = "/rooms/%s/state/m.room.member/%s" % (
  651. urllib.quote(self.room_id), self.other_id
  652. )
  653. # valid invite message
  654. content = '{"membership":"%s"}' % Membership.INVITE
  655. (code, response) = yield self.mock_resource.trigger("PUT", path, content)
  656. self.assertEquals(200, code, msg=str(response))
  657. (code, response) = yield self.mock_resource.trigger("GET", path, None)
  658. self.assertEquals(200, code, msg=str(response))
  659. self.assertEquals(json.loads(content), response)
  660. @defer.inlineCallbacks
  661. def test_rooms_members_other_custom_keys(self):
  662. self.other_id = "@zzsid1:red"
  663. path = "/rooms/%s/state/m.room.member/%s" % (
  664. urllib.quote(self.room_id), self.other_id
  665. )
  666. # valid invite message with custom key
  667. content = ('{"membership":"%s","invite_text":"%s"}' % (
  668. Membership.INVITE, "Join us!"
  669. ))
  670. (code, response) = yield self.mock_resource.trigger("PUT", path, content)
  671. self.assertEquals(200, code, msg=str(response))
  672. (code, response) = yield self.mock_resource.trigger("GET", path, None)
  673. self.assertEquals(200, code, msg=str(response))
  674. self.assertEquals(json.loads(content), response)
  675. class RoomMessagesTestCase(RestTestCase):
  676. """ Tests /rooms/$room_id/messages/$user_id/$msg_id REST events. """
  677. user_id = "@sid1:red"
  678. @defer.inlineCallbacks
  679. def setUp(self):
  680. self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
  681. self.auth_user_id = self.user_id
  682. hs = yield setup_test_homeserver(
  683. "red",
  684. http_client=None,
  685. replication_layer=Mock(),
  686. ratelimiter=NonCallableMock(spec_set=["send_message"]),
  687. )
  688. self.ratelimiter = hs.get_ratelimiter()
  689. self.ratelimiter.send_message.return_value = (True, 0)
  690. hs.get_handlers().federation_handler = Mock()
  691. def get_user_by_access_token(token=None, allow_guest=False):
  692. return {
  693. "user": UserID.from_string(self.auth_user_id),
  694. "token_id": 1,
  695. "is_guest": False,
  696. }
  697. hs.get_v1auth().get_user_by_access_token = get_user_by_access_token
  698. def _insert_client_ip(*args, **kwargs):
  699. return defer.succeed(None)
  700. hs.get_datastore().insert_client_ip = _insert_client_ip
  701. synapse.rest.client.v1.room.register_servlets(hs, self.mock_resource)
  702. self.room_id = yield self.create_room_as(self.user_id)
  703. def tearDown(self):
  704. pass
  705. @defer.inlineCallbacks
  706. def test_invalid_puts(self):
  707. path = "/rooms/%s/send/m.room.message/mid1" % (
  708. urllib.quote(self.room_id))
  709. # missing keys or invalid json
  710. (code, response) = yield self.mock_resource.trigger(
  711. "PUT", path, '{}'
  712. )
  713. self.assertEquals(400, code, msg=str(response))
  714. (code, response) = yield self.mock_resource.trigger(
  715. "PUT", path, '{"_name":"bob"}'
  716. )
  717. self.assertEquals(400, code, msg=str(response))
  718. (code, response) = yield self.mock_resource.trigger(
  719. "PUT", path, '{"nao'
  720. )
  721. self.assertEquals(400, code, msg=str(response))
  722. (code, response) = yield self.mock_resource.trigger(
  723. "PUT", path, '[{"_name":"bob"},{"_name":"jill"}]'
  724. )
  725. self.assertEquals(400, code, msg=str(response))
  726. (code, response) = yield self.mock_resource.trigger(
  727. "PUT", path, 'text only'
  728. )
  729. self.assertEquals(400, code, msg=str(response))
  730. (code, response) = yield self.mock_resource.trigger(
  731. "PUT", path, ''
  732. )
  733. self.assertEquals(400, code, msg=str(response))
  734. @defer.inlineCallbacks
  735. def test_rooms_messages_sent(self):
  736. path = "/rooms/%s/send/m.room.message/mid1" % (
  737. urllib.quote(self.room_id))
  738. content = '{"body":"test","msgtype":{"type":"a"}}'
  739. (code, response) = yield self.mock_resource.trigger("PUT", path, content)
  740. self.assertEquals(400, code, msg=str(response))
  741. # custom message types
  742. content = '{"body":"test","msgtype":"test.custom.text"}'
  743. (code, response) = yield self.mock_resource.trigger("PUT", path, content)
  744. self.assertEquals(200, code, msg=str(response))
  745. # (code, response) = yield self.mock_resource.trigger("GET", path, None)
  746. # self.assertEquals(200, code, msg=str(response))
  747. # self.assert_dict(json.loads(content), response)
  748. # m.text message type
  749. path = "/rooms/%s/send/m.room.message/mid2" % (
  750. urllib.quote(self.room_id))
  751. content = '{"body":"test2","msgtype":"m.text"}'
  752. (code, response) = yield self.mock_resource.trigger("PUT", path, content)
  753. self.assertEquals(200, code, msg=str(response))
  754. class RoomInitialSyncTestCase(RestTestCase):
  755. """ Tests /rooms/$room_id/initialSync. """
  756. user_id = "@sid1:red"
  757. @defer.inlineCallbacks
  758. def setUp(self):
  759. self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
  760. self.auth_user_id = self.user_id
  761. hs = yield setup_test_homeserver(
  762. "red",
  763. http_client=None,
  764. replication_layer=Mock(),
  765. ratelimiter=NonCallableMock(spec_set=[
  766. "send_message",
  767. ]),
  768. )
  769. self.ratelimiter = hs.get_ratelimiter()
  770. self.ratelimiter.send_message.return_value = (True, 0)
  771. hs.get_handlers().federation_handler = Mock()
  772. def get_user_by_access_token(token=None, allow_guest=False):
  773. return {
  774. "user": UserID.from_string(self.auth_user_id),
  775. "token_id": 1,
  776. "is_guest": False,
  777. }
  778. hs.get_v1auth().get_user_by_access_token = get_user_by_access_token
  779. def _insert_client_ip(*args, **kwargs):
  780. return defer.succeed(None)
  781. hs.get_datastore().insert_client_ip = _insert_client_ip
  782. synapse.rest.client.v1.room.register_servlets(hs, self.mock_resource)
  783. # create the room
  784. self.room_id = yield self.create_room_as(self.user_id)
  785. @defer.inlineCallbacks
  786. def test_initial_sync(self):
  787. (code, response) = yield self.mock_resource.trigger_get(
  788. "/rooms/%s/initialSync" % self.room_id
  789. )
  790. self.assertEquals(200, code)
  791. self.assertEquals(self.room_id, response["room_id"])
  792. self.assertEquals("join", response["membership"])
  793. # Room state is easier to assert on if we unpack it into a dict
  794. state = {}
  795. for event in response["state"]:
  796. if "state_key" not in event:
  797. continue
  798. t = event["type"]
  799. if t not in state:
  800. state[t] = []
  801. state[t].append(event)
  802. self.assertTrue("m.room.create" in state)
  803. self.assertTrue("messages" in response)
  804. self.assertTrue("chunk" in response["messages"])
  805. self.assertTrue("end" in response["messages"])
  806. self.assertTrue("presence" in response)
  807. presence_by_user = {
  808. e["content"]["user_id"]: e for e in response["presence"]
  809. }
  810. self.assertTrue(self.user_id in presence_by_user)
  811. self.assertEquals("m.presence", presence_by_user[self.user_id]["type"])
  812. class RoomMessageListTestCase(RestTestCase):
  813. """ Tests /rooms/$room_id/messages REST events. """
  814. user_id = "@sid1:red"
  815. @defer.inlineCallbacks
  816. def setUp(self):
  817. self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
  818. self.auth_user_id = self.user_id
  819. hs = yield setup_test_homeserver(
  820. "red",
  821. http_client=None,
  822. replication_layer=Mock(),
  823. ratelimiter=NonCallableMock(spec_set=["send_message"]),
  824. )
  825. self.ratelimiter = hs.get_ratelimiter()
  826. self.ratelimiter.send_message.return_value = (True, 0)
  827. hs.get_handlers().federation_handler = Mock()
  828. def get_user_by_access_token(token=None, allow_guest=False):
  829. return {
  830. "user": UserID.from_string(self.auth_user_id),
  831. "token_id": 1,
  832. "is_guest": False,
  833. }
  834. hs.get_v1auth().get_user_by_access_token = get_user_by_access_token
  835. def _insert_client_ip(*args, **kwargs):
  836. return defer.succeed(None)
  837. hs.get_datastore().insert_client_ip = _insert_client_ip
  838. synapse.rest.client.v1.room.register_servlets(hs, self.mock_resource)
  839. self.room_id = yield self.create_room_as(self.user_id)
  840. @defer.inlineCallbacks
  841. def test_topo_token_is_accepted(self):
  842. token = "t1-0_0_0_0_0_0"
  843. (code, response) = yield self.mock_resource.trigger_get(
  844. "/rooms/%s/messages?access_token=x&from=%s" %
  845. (self.room_id, token))
  846. self.assertEquals(200, code)
  847. self.assertTrue("start" in response)
  848. self.assertEquals(token, response['start'])
  849. self.assertTrue("chunk" in response)
  850. self.assertTrue("end" in response)
  851. @defer.inlineCallbacks
  852. def test_stream_token_is_accepted_for_fwd_pagianation(self):
  853. token = "s0_0_0_0_0_0"
  854. (code, response) = yield self.mock_resource.trigger_get(
  855. "/rooms/%s/messages?access_token=x&from=%s" %
  856. (self.room_id, token))
  857. self.assertEquals(200, code)
  858. self.assertTrue("start" in response)
  859. self.assertEquals(token, response['start'])
  860. self.assertTrue("chunk" in response)
  861. self.assertTrue("end" in response)