test_rooms.py 37 KB

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