test_event_reports.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2020 Dirk Klimpel
  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. import json
  16. import synapse.rest.admin
  17. from synapse.api.errors import Codes
  18. from synapse.rest.client.v1 import login, room
  19. from synapse.rest.client.v2_alpha import report_event
  20. from tests import unittest
  21. class EventReportsTestCase(unittest.HomeserverTestCase):
  22. servlets = [
  23. synapse.rest.admin.register_servlets,
  24. login.register_servlets,
  25. room.register_servlets,
  26. report_event.register_servlets,
  27. ]
  28. def prepare(self, reactor, clock, hs):
  29. self.store = hs.get_datastore()
  30. self.admin_user = self.register_user("admin", "pass", admin=True)
  31. self.admin_user_tok = self.login("admin", "pass")
  32. self.other_user = self.register_user("user", "pass")
  33. self.other_user_tok = self.login("user", "pass")
  34. self.room_id1 = self.helper.create_room_as(
  35. self.other_user, tok=self.other_user_tok, is_public=True
  36. )
  37. self.helper.join(self.room_id1, user=self.admin_user, tok=self.admin_user_tok)
  38. self.room_id2 = self.helper.create_room_as(
  39. self.other_user, tok=self.other_user_tok, is_public=True
  40. )
  41. self.helper.join(self.room_id2, user=self.admin_user, tok=self.admin_user_tok)
  42. # Two rooms and two users. Every user sends and reports every room event
  43. for i in range(5):
  44. self._create_event_and_report(
  45. room_id=self.room_id1, user_tok=self.other_user_tok,
  46. )
  47. for i in range(5):
  48. self._create_event_and_report(
  49. room_id=self.room_id2, user_tok=self.other_user_tok,
  50. )
  51. for i in range(5):
  52. self._create_event_and_report(
  53. room_id=self.room_id1, user_tok=self.admin_user_tok,
  54. )
  55. for i in range(5):
  56. self._create_event_and_report(
  57. room_id=self.room_id2, user_tok=self.admin_user_tok,
  58. )
  59. self.url = "/_synapse/admin/v1/event_reports"
  60. def test_requester_is_no_admin(self):
  61. """
  62. If the user is not a server admin, an error 403 is returned.
  63. """
  64. request, channel = self.make_request(
  65. "GET", self.url, access_token=self.other_user_tok,
  66. )
  67. self.render(request)
  68. self.assertEqual(403, int(channel.result["code"]), msg=channel.result["body"])
  69. self.assertEqual(Codes.FORBIDDEN, channel.json_body["errcode"])
  70. def test_default_success(self):
  71. """
  72. Testing list of reported events
  73. """
  74. request, channel = self.make_request(
  75. "GET", self.url, access_token=self.admin_user_tok,
  76. )
  77. self.render(request)
  78. self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
  79. self.assertEqual(channel.json_body["total"], 20)
  80. self.assertEqual(len(channel.json_body["event_reports"]), 20)
  81. self.assertNotIn("next_token", channel.json_body)
  82. self._check_fields(channel.json_body["event_reports"])
  83. def test_limit(self):
  84. """
  85. Testing list of reported events with limit
  86. """
  87. request, channel = self.make_request(
  88. "GET", self.url + "?limit=5", access_token=self.admin_user_tok,
  89. )
  90. self.render(request)
  91. self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
  92. self.assertEqual(channel.json_body["total"], 20)
  93. self.assertEqual(len(channel.json_body["event_reports"]), 5)
  94. self.assertEqual(channel.json_body["next_token"], 5)
  95. self._check_fields(channel.json_body["event_reports"])
  96. def test_from(self):
  97. """
  98. Testing list of reported events with a defined starting point (from)
  99. """
  100. request, channel = self.make_request(
  101. "GET", self.url + "?from=5", access_token=self.admin_user_tok,
  102. )
  103. self.render(request)
  104. self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
  105. self.assertEqual(channel.json_body["total"], 20)
  106. self.assertEqual(len(channel.json_body["event_reports"]), 15)
  107. self.assertNotIn("next_token", channel.json_body)
  108. self._check_fields(channel.json_body["event_reports"])
  109. def test_limit_and_from(self):
  110. """
  111. Testing list of reported events with a defined starting point and limit
  112. """
  113. request, channel = self.make_request(
  114. "GET", self.url + "?from=5&limit=10", access_token=self.admin_user_tok,
  115. )
  116. self.render(request)
  117. self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
  118. self.assertEqual(channel.json_body["total"], 20)
  119. self.assertEqual(channel.json_body["next_token"], 15)
  120. self.assertEqual(len(channel.json_body["event_reports"]), 10)
  121. self._check_fields(channel.json_body["event_reports"])
  122. def test_filter_room(self):
  123. """
  124. Testing list of reported events with a filter of room
  125. """
  126. request, channel = self.make_request(
  127. "GET",
  128. self.url + "?room_id=%s" % self.room_id1,
  129. access_token=self.admin_user_tok,
  130. )
  131. self.render(request)
  132. self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
  133. self.assertEqual(channel.json_body["total"], 10)
  134. self.assertEqual(len(channel.json_body["event_reports"]), 10)
  135. self.assertNotIn("next_token", channel.json_body)
  136. self._check_fields(channel.json_body["event_reports"])
  137. for report in channel.json_body["event_reports"]:
  138. self.assertEqual(report["room_id"], self.room_id1)
  139. def test_filter_user(self):
  140. """
  141. Testing list of reported events with a filter of user
  142. """
  143. request, channel = self.make_request(
  144. "GET",
  145. self.url + "?user_id=%s" % self.other_user,
  146. access_token=self.admin_user_tok,
  147. )
  148. self.render(request)
  149. self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
  150. self.assertEqual(channel.json_body["total"], 10)
  151. self.assertEqual(len(channel.json_body["event_reports"]), 10)
  152. self.assertNotIn("next_token", channel.json_body)
  153. self._check_fields(channel.json_body["event_reports"])
  154. for report in channel.json_body["event_reports"]:
  155. self.assertEqual(report["user_id"], self.other_user)
  156. def test_filter_user_and_room(self):
  157. """
  158. Testing list of reported events with a filter of user and room
  159. """
  160. request, channel = self.make_request(
  161. "GET",
  162. self.url + "?user_id=%s&room_id=%s" % (self.other_user, self.room_id1),
  163. access_token=self.admin_user_tok,
  164. )
  165. self.render(request)
  166. self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
  167. self.assertEqual(channel.json_body["total"], 5)
  168. self.assertEqual(len(channel.json_body["event_reports"]), 5)
  169. self.assertNotIn("next_token", channel.json_body)
  170. self._check_fields(channel.json_body["event_reports"])
  171. for report in channel.json_body["event_reports"]:
  172. self.assertEqual(report["user_id"], self.other_user)
  173. self.assertEqual(report["room_id"], self.room_id1)
  174. def test_valid_search_order(self):
  175. """
  176. Testing search order. Order by timestamps.
  177. """
  178. # fetch the most recent first, largest timestamp
  179. request, channel = self.make_request(
  180. "GET", self.url + "?dir=b", access_token=self.admin_user_tok,
  181. )
  182. self.render(request)
  183. self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
  184. self.assertEqual(channel.json_body["total"], 20)
  185. self.assertEqual(len(channel.json_body["event_reports"]), 20)
  186. report = 1
  187. while report < len(channel.json_body["event_reports"]):
  188. self.assertGreaterEqual(
  189. channel.json_body["event_reports"][report - 1]["received_ts"],
  190. channel.json_body["event_reports"][report]["received_ts"],
  191. )
  192. report += 1
  193. # fetch the oldest first, smallest timestamp
  194. request, channel = self.make_request(
  195. "GET", self.url + "?dir=f", access_token=self.admin_user_tok,
  196. )
  197. self.render(request)
  198. self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
  199. self.assertEqual(channel.json_body["total"], 20)
  200. self.assertEqual(len(channel.json_body["event_reports"]), 20)
  201. report = 1
  202. while report < len(channel.json_body["event_reports"]):
  203. self.assertLessEqual(
  204. channel.json_body["event_reports"][report - 1]["received_ts"],
  205. channel.json_body["event_reports"][report]["received_ts"],
  206. )
  207. report += 1
  208. def test_invalid_search_order(self):
  209. """
  210. Testing that a invalid search order returns a 400
  211. """
  212. request, channel = self.make_request(
  213. "GET", self.url + "?dir=bar", access_token=self.admin_user_tok,
  214. )
  215. self.render(request)
  216. self.assertEqual(400, int(channel.result["code"]), msg=channel.result["body"])
  217. self.assertEqual(Codes.INVALID_PARAM, channel.json_body["errcode"])
  218. self.assertEqual("Unknown direction: bar", channel.json_body["error"])
  219. def test_limit_is_negative(self):
  220. """
  221. Testing that a negative list parameter returns a 400
  222. """
  223. request, channel = self.make_request(
  224. "GET", self.url + "?limit=-5", access_token=self.admin_user_tok,
  225. )
  226. self.render(request)
  227. self.assertEqual(400, int(channel.result["code"]), msg=channel.result["body"])
  228. self.assertEqual(Codes.INVALID_PARAM, channel.json_body["errcode"])
  229. def test_from_is_negative(self):
  230. """
  231. Testing that a negative from parameter returns a 400
  232. """
  233. request, channel = self.make_request(
  234. "GET", self.url + "?from=-5", access_token=self.admin_user_tok,
  235. )
  236. self.render(request)
  237. self.assertEqual(400, int(channel.result["code"]), msg=channel.result["body"])
  238. self.assertEqual(Codes.INVALID_PARAM, channel.json_body["errcode"])
  239. def test_next_token(self):
  240. """
  241. Testing that `next_token` appears at the right place
  242. """
  243. # `next_token` does not appear
  244. # Number of results is the number of entries
  245. request, channel = self.make_request(
  246. "GET", self.url + "?limit=20", access_token=self.admin_user_tok,
  247. )
  248. self.render(request)
  249. self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
  250. self.assertEqual(channel.json_body["total"], 20)
  251. self.assertEqual(len(channel.json_body["event_reports"]), 20)
  252. self.assertNotIn("next_token", channel.json_body)
  253. # `next_token` does not appear
  254. # Number of max results is larger than the number of entries
  255. request, channel = self.make_request(
  256. "GET", self.url + "?limit=21", access_token=self.admin_user_tok,
  257. )
  258. self.render(request)
  259. self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
  260. self.assertEqual(channel.json_body["total"], 20)
  261. self.assertEqual(len(channel.json_body["event_reports"]), 20)
  262. self.assertNotIn("next_token", channel.json_body)
  263. # `next_token` does appear
  264. # Number of max results is smaller than the number of entries
  265. request, channel = self.make_request(
  266. "GET", self.url + "?limit=19", access_token=self.admin_user_tok,
  267. )
  268. self.render(request)
  269. self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
  270. self.assertEqual(channel.json_body["total"], 20)
  271. self.assertEqual(len(channel.json_body["event_reports"]), 19)
  272. self.assertEqual(channel.json_body["next_token"], 19)
  273. # Check
  274. # Set `from` to value of `next_token` for request remaining entries
  275. # `next_token` does not appear
  276. request, channel = self.make_request(
  277. "GET", self.url + "?from=19", access_token=self.admin_user_tok,
  278. )
  279. self.render(request)
  280. self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
  281. self.assertEqual(channel.json_body["total"], 20)
  282. self.assertEqual(len(channel.json_body["event_reports"]), 1)
  283. self.assertNotIn("next_token", channel.json_body)
  284. def _create_event_and_report(self, room_id, user_tok):
  285. """Create and report events
  286. """
  287. resp = self.helper.send(room_id, tok=user_tok)
  288. event_id = resp["event_id"]
  289. request, channel = self.make_request(
  290. "POST",
  291. "rooms/%s/report/%s" % (room_id, event_id),
  292. json.dumps({"score": -100, "reason": "this makes me sad"}),
  293. access_token=user_tok,
  294. )
  295. self.render(request)
  296. self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
  297. def _check_fields(self, content):
  298. """Checks that all attributes are present in a event report
  299. """
  300. for c in content:
  301. self.assertIn("id", c)
  302. self.assertIn("received_ts", c)
  303. self.assertIn("room_id", c)
  304. self.assertIn("event_id", c)
  305. self.assertIn("user_id", c)
  306. self.assertIn("reason", c)
  307. self.assertIn("content", c)
  308. self.assertIn("sender", c)
  309. self.assertIn("room_alias", c)
  310. self.assertIn("event_json", c)
  311. self.assertIn("score", c["content"])
  312. self.assertIn("reason", c["content"])
  313. self.assertIn("auth_events", c["event_json"])
  314. self.assertIn("type", c["event_json"])
  315. self.assertIn("room_id", c["event_json"])
  316. self.assertIn("sender", c["event_json"])
  317. self.assertIn("content", c["event_json"])