test_rooms.py 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052
  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. from six.moves.urllib import parse as urlparse
  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. federation_client=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_auth().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_auth()
  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=404)
  217. yield self.leave(room=room, user=usr, expect_code=404)
  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. federation_client=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_auth().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. federation_client=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_auth().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. @defer.inlineCallbacks
  429. def test_post_room_no_keys(self):
  430. # POST with no config keys, expect new room id
  431. (code, response) = yield self.mock_resource.trigger("POST",
  432. "/createRoom",
  433. "{}")
  434. self.assertEquals(200, code, response)
  435. self.assertTrue("room_id" in response)
  436. @defer.inlineCallbacks
  437. def test_post_room_visibility_key(self):
  438. # POST with visibility config key, expect new room id
  439. (code, response) = yield self.mock_resource.trigger(
  440. "POST",
  441. "/createRoom",
  442. '{"visibility":"private"}')
  443. self.assertEquals(200, code)
  444. self.assertTrue("room_id" in response)
  445. @defer.inlineCallbacks
  446. def test_post_room_custom_key(self):
  447. # POST with custom config keys, expect new room id
  448. (code, response) = yield self.mock_resource.trigger(
  449. "POST",
  450. "/createRoom",
  451. '{"custom":"stuff"}')
  452. self.assertEquals(200, code)
  453. self.assertTrue("room_id" in response)
  454. @defer.inlineCallbacks
  455. def test_post_room_known_and_unknown_keys(self):
  456. # POST with custom + known config keys, expect new room id
  457. (code, response) = yield self.mock_resource.trigger(
  458. "POST",
  459. "/createRoom",
  460. '{"visibility":"private","custom":"things"}')
  461. self.assertEquals(200, code)
  462. self.assertTrue("room_id" in response)
  463. @defer.inlineCallbacks
  464. def test_post_room_invalid_content(self):
  465. # POST with invalid content / paths, expect 400
  466. (code, response) = yield self.mock_resource.trigger(
  467. "POST",
  468. "/createRoom",
  469. '{"visibili')
  470. self.assertEquals(400, code)
  471. (code, response) = yield self.mock_resource.trigger(
  472. "POST",
  473. "/createRoom",
  474. '["hello"]')
  475. self.assertEquals(400, code)
  476. class RoomTopicTestCase(RestTestCase):
  477. """ Tests /rooms/$room_id/topic REST events. """
  478. user_id = "@sid1:red"
  479. @defer.inlineCallbacks
  480. def setUp(self):
  481. self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
  482. self.auth_user_id = self.user_id
  483. hs = yield setup_test_homeserver(
  484. "red",
  485. http_client=None,
  486. federation_client=Mock(),
  487. ratelimiter=NonCallableMock(spec_set=["send_message"]),
  488. )
  489. self.ratelimiter = hs.get_ratelimiter()
  490. self.ratelimiter.send_message.return_value = (True, 0)
  491. hs.get_handlers().federation_handler = Mock()
  492. def get_user_by_access_token(token=None, allow_guest=False):
  493. return {
  494. "user": UserID.from_string(self.auth_user_id),
  495. "token_id": 1,
  496. "is_guest": False,
  497. }
  498. hs.get_auth().get_user_by_access_token = get_user_by_access_token
  499. def _insert_client_ip(*args, **kwargs):
  500. return defer.succeed(None)
  501. hs.get_datastore().insert_client_ip = _insert_client_ip
  502. synapse.rest.client.v1.room.register_servlets(hs, self.mock_resource)
  503. # create the room
  504. self.room_id = yield self.create_room_as(self.user_id)
  505. self.path = "/rooms/%s/state/m.room.topic" % (self.room_id,)
  506. def tearDown(self):
  507. pass
  508. @defer.inlineCallbacks
  509. def test_invalid_puts(self):
  510. # missing keys or invalid json
  511. (code, response) = yield self.mock_resource.trigger(
  512. "PUT", self.path, '{}'
  513. )
  514. self.assertEquals(400, code, msg=str(response))
  515. (code, response) = yield self.mock_resource.trigger(
  516. "PUT", self.path, '{"_name":"bob"}'
  517. )
  518. self.assertEquals(400, code, msg=str(response))
  519. (code, response) = yield self.mock_resource.trigger(
  520. "PUT", self.path, '{"nao'
  521. )
  522. self.assertEquals(400, code, msg=str(response))
  523. (code, response) = yield self.mock_resource.trigger(
  524. "PUT", self.path, '[{"_name":"bob"},{"_name":"jill"}]'
  525. )
  526. self.assertEquals(400, code, msg=str(response))
  527. (code, response) = yield self.mock_resource.trigger(
  528. "PUT", self.path, 'text only'
  529. )
  530. self.assertEquals(400, code, msg=str(response))
  531. (code, response) = yield self.mock_resource.trigger(
  532. "PUT", self.path, ''
  533. )
  534. self.assertEquals(400, code, msg=str(response))
  535. # valid key, wrong type
  536. content = '{"topic":["Topic name"]}'
  537. (code, response) = yield self.mock_resource.trigger(
  538. "PUT", self.path, content
  539. )
  540. self.assertEquals(400, code, msg=str(response))
  541. @defer.inlineCallbacks
  542. def test_rooms_topic(self):
  543. # nothing should be there
  544. (code, response) = yield self.mock_resource.trigger_get(self.path)
  545. self.assertEquals(404, code, msg=str(response))
  546. # valid put
  547. content = '{"topic":"Topic name"}'
  548. (code, response) = yield self.mock_resource.trigger(
  549. "PUT", self.path, content
  550. )
  551. self.assertEquals(200, code, msg=str(response))
  552. # valid get
  553. (code, response) = yield self.mock_resource.trigger_get(self.path)
  554. self.assertEquals(200, code, msg=str(response))
  555. self.assert_dict(json.loads(content), response)
  556. @defer.inlineCallbacks
  557. def test_rooms_topic_with_extra_keys(self):
  558. # valid put with extra keys
  559. content = '{"topic":"Seasons","subtopic":"Summer"}'
  560. (code, response) = yield self.mock_resource.trigger(
  561. "PUT", self.path, content
  562. )
  563. self.assertEquals(200, code, msg=str(response))
  564. # valid get
  565. (code, response) = yield self.mock_resource.trigger_get(self.path)
  566. self.assertEquals(200, code, msg=str(response))
  567. self.assert_dict(json.loads(content), response)
  568. class RoomMemberStateTestCase(RestTestCase):
  569. """ Tests /rooms/$room_id/members/$user_id/state REST events. """
  570. user_id = "@sid1:red"
  571. @defer.inlineCallbacks
  572. def setUp(self):
  573. self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
  574. self.auth_user_id = self.user_id
  575. hs = yield setup_test_homeserver(
  576. "red",
  577. http_client=None,
  578. federation_client=Mock(),
  579. ratelimiter=NonCallableMock(spec_set=["send_message"]),
  580. )
  581. self.ratelimiter = hs.get_ratelimiter()
  582. self.ratelimiter.send_message.return_value = (True, 0)
  583. hs.get_handlers().federation_handler = Mock()
  584. def get_user_by_access_token(token=None, allow_guest=False):
  585. return {
  586. "user": UserID.from_string(self.auth_user_id),
  587. "token_id": 1,
  588. "is_guest": False,
  589. }
  590. hs.get_auth().get_user_by_access_token = get_user_by_access_token
  591. def _insert_client_ip(*args, **kwargs):
  592. return defer.succeed(None)
  593. hs.get_datastore().insert_client_ip = _insert_client_ip
  594. synapse.rest.client.v1.room.register_servlets(hs, self.mock_resource)
  595. self.room_id = yield self.create_room_as(self.user_id)
  596. def tearDown(self):
  597. pass
  598. @defer.inlineCallbacks
  599. def test_invalid_puts(self):
  600. path = "/rooms/%s/state/m.room.member/%s" % (self.room_id, self.user_id)
  601. # missing keys or invalid json
  602. (code, response) = yield self.mock_resource.trigger("PUT", path, '{}')
  603. self.assertEquals(400, code, msg=str(response))
  604. (code, response) = yield self.mock_resource.trigger(
  605. "PUT", path, '{"_name":"bob"}'
  606. )
  607. self.assertEquals(400, code, msg=str(response))
  608. (code, response) = yield self.mock_resource.trigger(
  609. "PUT", path, '{"nao'
  610. )
  611. self.assertEquals(400, code, msg=str(response))
  612. (code, response) = yield self.mock_resource.trigger(
  613. "PUT", path, '[{"_name":"bob"},{"_name":"jill"}]'
  614. )
  615. self.assertEquals(400, code, msg=str(response))
  616. (code, response) = yield self.mock_resource.trigger(
  617. "PUT", path, 'text only'
  618. )
  619. self.assertEquals(400, code, msg=str(response))
  620. (code, response) = yield self.mock_resource.trigger(
  621. "PUT", path, ''
  622. )
  623. self.assertEquals(400, code, msg=str(response))
  624. # valid keys, wrong types
  625. content = ('{"membership":["%s","%s","%s"]}' % (
  626. Membership.INVITE, Membership.JOIN, Membership.LEAVE
  627. ))
  628. (code, response) = yield self.mock_resource.trigger("PUT", path, content)
  629. self.assertEquals(400, code, msg=str(response))
  630. @defer.inlineCallbacks
  631. def test_rooms_members_self(self):
  632. path = "/rooms/%s/state/m.room.member/%s" % (
  633. urlparse.quote(self.room_id), self.user_id
  634. )
  635. # valid join message (NOOP since we made the room)
  636. content = '{"membership":"%s"}' % Membership.JOIN
  637. (code, response) = yield self.mock_resource.trigger("PUT", path, content)
  638. self.assertEquals(200, code, msg=str(response))
  639. (code, response) = yield self.mock_resource.trigger("GET", path, None)
  640. self.assertEquals(200, code, msg=str(response))
  641. expected_response = {
  642. "membership": Membership.JOIN,
  643. }
  644. self.assertEquals(expected_response, response)
  645. @defer.inlineCallbacks
  646. def test_rooms_members_other(self):
  647. self.other_id = "@zzsid1:red"
  648. path = "/rooms/%s/state/m.room.member/%s" % (
  649. urlparse.quote(self.room_id), self.other_id
  650. )
  651. # valid invite message
  652. content = '{"membership":"%s"}' % Membership.INVITE
  653. (code, response) = yield self.mock_resource.trigger("PUT", path, content)
  654. self.assertEquals(200, code, msg=str(response))
  655. (code, response) = yield self.mock_resource.trigger("GET", path, None)
  656. self.assertEquals(200, code, msg=str(response))
  657. self.assertEquals(json.loads(content), response)
  658. @defer.inlineCallbacks
  659. def test_rooms_members_other_custom_keys(self):
  660. self.other_id = "@zzsid1:red"
  661. path = "/rooms/%s/state/m.room.member/%s" % (
  662. urlparse.quote(self.room_id), self.other_id
  663. )
  664. # valid invite message with custom key
  665. content = ('{"membership":"%s","invite_text":"%s"}' % (
  666. Membership.INVITE, "Join us!"
  667. ))
  668. (code, response) = yield self.mock_resource.trigger("PUT", path, content)
  669. self.assertEquals(200, code, msg=str(response))
  670. (code, response) = yield self.mock_resource.trigger("GET", path, None)
  671. self.assertEquals(200, code, msg=str(response))
  672. self.assertEquals(json.loads(content), response)
  673. class RoomMessagesTestCase(RestTestCase):
  674. """ Tests /rooms/$room_id/messages/$user_id/$msg_id REST events. """
  675. user_id = "@sid1:red"
  676. @defer.inlineCallbacks
  677. def setUp(self):
  678. self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
  679. self.auth_user_id = self.user_id
  680. hs = yield setup_test_homeserver(
  681. "red",
  682. http_client=None,
  683. federation_client=Mock(),
  684. ratelimiter=NonCallableMock(spec_set=["send_message"]),
  685. )
  686. self.ratelimiter = hs.get_ratelimiter()
  687. self.ratelimiter.send_message.return_value = (True, 0)
  688. hs.get_handlers().federation_handler = Mock()
  689. def get_user_by_access_token(token=None, allow_guest=False):
  690. return {
  691. "user": UserID.from_string(self.auth_user_id),
  692. "token_id": 1,
  693. "is_guest": False,
  694. }
  695. hs.get_auth().get_user_by_access_token = get_user_by_access_token
  696. def _insert_client_ip(*args, **kwargs):
  697. return defer.succeed(None)
  698. hs.get_datastore().insert_client_ip = _insert_client_ip
  699. synapse.rest.client.v1.room.register_servlets(hs, self.mock_resource)
  700. self.room_id = yield self.create_room_as(self.user_id)
  701. def tearDown(self):
  702. pass
  703. @defer.inlineCallbacks
  704. def test_invalid_puts(self):
  705. path = "/rooms/%s/send/m.room.message/mid1" % (
  706. urlparse.quote(self.room_id))
  707. # missing keys or invalid json
  708. (code, response) = yield self.mock_resource.trigger(
  709. "PUT", path, '{}'
  710. )
  711. self.assertEquals(400, code, msg=str(response))
  712. (code, response) = yield self.mock_resource.trigger(
  713. "PUT", path, '{"_name":"bob"}'
  714. )
  715. self.assertEquals(400, code, msg=str(response))
  716. (code, response) = yield self.mock_resource.trigger(
  717. "PUT", path, '{"nao'
  718. )
  719. self.assertEquals(400, code, msg=str(response))
  720. (code, response) = yield self.mock_resource.trigger(
  721. "PUT", path, '[{"_name":"bob"},{"_name":"jill"}]'
  722. )
  723. self.assertEquals(400, code, msg=str(response))
  724. (code, response) = yield self.mock_resource.trigger(
  725. "PUT", path, 'text only'
  726. )
  727. self.assertEquals(400, code, msg=str(response))
  728. (code, response) = yield self.mock_resource.trigger(
  729. "PUT", path, ''
  730. )
  731. self.assertEquals(400, code, msg=str(response))
  732. @defer.inlineCallbacks
  733. def test_rooms_messages_sent(self):
  734. path = "/rooms/%s/send/m.room.message/mid1" % (
  735. urlparse.quote(self.room_id))
  736. content = '{"body":"test","msgtype":{"type":"a"}}'
  737. (code, response) = yield self.mock_resource.trigger("PUT", path, content)
  738. self.assertEquals(400, code, msg=str(response))
  739. # custom message types
  740. content = '{"body":"test","msgtype":"test.custom.text"}'
  741. (code, response) = yield self.mock_resource.trigger("PUT", path, content)
  742. self.assertEquals(200, code, msg=str(response))
  743. # (code, response) = yield self.mock_resource.trigger("GET", path, None)
  744. # self.assertEquals(200, code, msg=str(response))
  745. # self.assert_dict(json.loads(content), response)
  746. # m.text message type
  747. path = "/rooms/%s/send/m.room.message/mid2" % (
  748. urlparse.quote(self.room_id))
  749. content = '{"body":"test2","msgtype":"m.text"}'
  750. (code, response) = yield self.mock_resource.trigger("PUT", path, content)
  751. self.assertEquals(200, code, msg=str(response))
  752. class RoomInitialSyncTestCase(RestTestCase):
  753. """ Tests /rooms/$room_id/initialSync. """
  754. user_id = "@sid1:red"
  755. @defer.inlineCallbacks
  756. def setUp(self):
  757. self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
  758. self.auth_user_id = self.user_id
  759. hs = yield setup_test_homeserver(
  760. "red",
  761. http_client=None,
  762. federation_client=Mock(),
  763. ratelimiter=NonCallableMock(spec_set=[
  764. "send_message",
  765. ]),
  766. )
  767. self.ratelimiter = hs.get_ratelimiter()
  768. self.ratelimiter.send_message.return_value = (True, 0)
  769. hs.get_handlers().federation_handler = Mock()
  770. def get_user_by_access_token(token=None, allow_guest=False):
  771. return {
  772. "user": UserID.from_string(self.auth_user_id),
  773. "token_id": 1,
  774. "is_guest": False,
  775. }
  776. hs.get_auth().get_user_by_access_token = get_user_by_access_token
  777. def _insert_client_ip(*args, **kwargs):
  778. return defer.succeed(None)
  779. hs.get_datastore().insert_client_ip = _insert_client_ip
  780. synapse.rest.client.v1.room.register_servlets(hs, self.mock_resource)
  781. # create the room
  782. self.room_id = yield self.create_room_as(self.user_id)
  783. @defer.inlineCallbacks
  784. def test_initial_sync(self):
  785. (code, response) = yield self.mock_resource.trigger_get(
  786. "/rooms/%s/initialSync" % self.room_id
  787. )
  788. self.assertEquals(200, code)
  789. self.assertEquals(self.room_id, response["room_id"])
  790. self.assertEquals("join", response["membership"])
  791. # Room state is easier to assert on if we unpack it into a dict
  792. state = {}
  793. for event in response["state"]:
  794. if "state_key" not in event:
  795. continue
  796. t = event["type"]
  797. if t not in state:
  798. state[t] = []
  799. state[t].append(event)
  800. self.assertTrue("m.room.create" in state)
  801. self.assertTrue("messages" in response)
  802. self.assertTrue("chunk" in response["messages"])
  803. self.assertTrue("end" in response["messages"])
  804. self.assertTrue("presence" in response)
  805. presence_by_user = {
  806. e["content"]["user_id"]: e for e in response["presence"]
  807. }
  808. self.assertTrue(self.user_id in presence_by_user)
  809. self.assertEquals("m.presence", presence_by_user[self.user_id]["type"])
  810. class RoomMessageListTestCase(RestTestCase):
  811. """ Tests /rooms/$room_id/messages REST events. """
  812. user_id = "@sid1:red"
  813. @defer.inlineCallbacks
  814. def setUp(self):
  815. self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
  816. self.auth_user_id = self.user_id
  817. hs = yield setup_test_homeserver(
  818. "red",
  819. http_client=None,
  820. federation_client=Mock(),
  821. ratelimiter=NonCallableMock(spec_set=["send_message"]),
  822. )
  823. self.ratelimiter = hs.get_ratelimiter()
  824. self.ratelimiter.send_message.return_value = (True, 0)
  825. hs.get_handlers().federation_handler = Mock()
  826. def get_user_by_access_token(token=None, allow_guest=False):
  827. return {
  828. "user": UserID.from_string(self.auth_user_id),
  829. "token_id": 1,
  830. "is_guest": False,
  831. }
  832. hs.get_auth().get_user_by_access_token = get_user_by_access_token
  833. def _insert_client_ip(*args, **kwargs):
  834. return defer.succeed(None)
  835. hs.get_datastore().insert_client_ip = _insert_client_ip
  836. synapse.rest.client.v1.room.register_servlets(hs, self.mock_resource)
  837. self.room_id = yield self.create_room_as(self.user_id)
  838. @defer.inlineCallbacks
  839. def test_topo_token_is_accepted(self):
  840. token = "t1-0_0_0_0_0_0_0_0_0"
  841. (code, response) = yield self.mock_resource.trigger_get(
  842. "/rooms/%s/messages?access_token=x&from=%s" %
  843. (self.room_id, token))
  844. self.assertEquals(200, code)
  845. self.assertTrue("start" in response)
  846. self.assertEquals(token, response['start'])
  847. self.assertTrue("chunk" in response)
  848. self.assertTrue("end" in response)
  849. @defer.inlineCallbacks
  850. def test_stream_token_is_accepted_for_fwd_pagianation(self):
  851. token = "s0_0_0_0_0_0_0_0_0"
  852. (code, response) = yield self.mock_resource.trigger_get(
  853. "/rooms/%s/messages?access_token=x&from=%s" %
  854. (self.room_id, token))
  855. self.assertEquals(200, code)
  856. self.assertTrue("start" in response)
  857. self.assertEquals(token, response['start'])
  858. self.assertTrue("chunk" in response)
  859. self.assertTrue("end" in response)