Make reason and score optional for report_event (#10077)
Implements MSC2414: https://github.com/matrix-org/matrix-doc/pull/2414 See #8551 Signed-off-by: Callum Brown <callum@calcuode.com>pull/10090/head
							parent
							
								
									f828a70be3
								
							
						
					
					
						commit
						8fb9af570f
					
				|  | @ -0,0 +1 @@ | |||
| Make reason and score parameters optional for reporting content. Implements [MSC2414](https://github.com/matrix-org/matrix-doc/pull/2414). Contributed by Callum Brown. | ||||
|  | @ -75,9 +75,9 @@ The following fields are returned in the JSON response body: | |||
| * `name`: string - The name of the room. | ||||
| * `event_id`: string - The ID of the reported event. | ||||
| * `user_id`: string - This is the user who reported the event and wrote the reason. | ||||
| * `reason`: string - Comment made by the `user_id` in this report. May be blank. | ||||
| * `reason`: string - Comment made by the `user_id` in this report. May be blank or `null`. | ||||
| * `score`: integer - Content is reported based upon a negative score, where -100 is | ||||
|   "most offensive" and 0 is "inoffensive". | ||||
|   "most offensive" and 0 is "inoffensive". May be `null`. | ||||
| * `sender`: string - This is the ID of the user who sent the original message/event that | ||||
|   was reported. | ||||
| * `canonical_alias`: string - The canonical alias of the room. `null` if the room does not | ||||
|  |  | |||
|  | @ -16,11 +16,7 @@ import logging | |||
| from http import HTTPStatus | ||||
| 
 | ||||
| from synapse.api.errors import Codes, SynapseError | ||||
| from synapse.http.servlet import ( | ||||
|     RestServlet, | ||||
|     assert_params_in_dict, | ||||
|     parse_json_object_from_request, | ||||
| ) | ||||
| from synapse.http.servlet import RestServlet, parse_json_object_from_request | ||||
| 
 | ||||
| from ._base import client_patterns | ||||
| 
 | ||||
|  | @ -42,15 +38,14 @@ class ReportEventRestServlet(RestServlet): | |||
|         user_id = requester.user.to_string() | ||||
| 
 | ||||
|         body = parse_json_object_from_request(request) | ||||
|         assert_params_in_dict(body, ("reason", "score")) | ||||
| 
 | ||||
|         if not isinstance(body["reason"], str): | ||||
|         if not isinstance(body.get("reason", ""), str): | ||||
|             raise SynapseError( | ||||
|                 HTTPStatus.BAD_REQUEST, | ||||
|                 "Param 'reason' must be a string", | ||||
|                 Codes.BAD_JSON, | ||||
|             ) | ||||
|         if not isinstance(body["score"], int): | ||||
|         if not isinstance(body.get("score", 0), int): | ||||
|             raise SynapseError( | ||||
|                 HTTPStatus.BAD_REQUEST, | ||||
|                 "Param 'score' must be an integer", | ||||
|  | @ -61,7 +56,7 @@ class ReportEventRestServlet(RestServlet): | |||
|             room_id=room_id, | ||||
|             event_id=event_id, | ||||
|             user_id=user_id, | ||||
|             reason=body["reason"], | ||||
|             reason=body.get("reason"), | ||||
|             content=body, | ||||
|             received_ts=self.clock.time_msec(), | ||||
|         ) | ||||
|  |  | |||
|  | @ -1498,7 +1498,7 @@ class RoomStore(RoomBackgroundUpdateStore, RoomWorkerStore, SearchStore): | |||
|         room_id: str, | ||||
|         event_id: str, | ||||
|         user_id: str, | ||||
|         reason: str, | ||||
|         reason: Optional[str], | ||||
|         content: JsonDict, | ||||
|         received_ts: int, | ||||
|     ) -> None: | ||||
|  |  | |||
|  | @ -64,7 +64,7 @@ class EventReportsTestCase(unittest.HomeserverTestCase): | |||
|                 user_tok=self.admin_user_tok, | ||||
|             ) | ||||
|         for _ in range(5): | ||||
|             self._create_event_and_report( | ||||
|             self._create_event_and_report_without_parameters( | ||||
|                 room_id=self.room_id2, | ||||
|                 user_tok=self.admin_user_tok, | ||||
|             ) | ||||
|  | @ -378,6 +378,19 @@ class EventReportsTestCase(unittest.HomeserverTestCase): | |||
|         ) | ||||
|         self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"]) | ||||
| 
 | ||||
|     def _create_event_and_report_without_parameters(self, room_id, user_tok): | ||||
|         """Create and report an event, but omit reason and score""" | ||||
|         resp = self.helper.send(room_id, tok=user_tok) | ||||
|         event_id = resp["event_id"] | ||||
| 
 | ||||
|         channel = self.make_request( | ||||
|             "POST", | ||||
|             "rooms/%s/report/%s" % (room_id, event_id), | ||||
|             json.dumps({}), | ||||
|             access_token=user_tok, | ||||
|         ) | ||||
|         self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"]) | ||||
| 
 | ||||
|     def _check_fields(self, content): | ||||
|         """Checks that all attributes are present in an event report""" | ||||
|         for c in content: | ||||
|  |  | |||
|  | @ -0,0 +1,83 @@ | |||
| # Copyright 2021 Callum Brown | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
| 
 | ||||
| import json | ||||
| 
 | ||||
| import synapse.rest.admin | ||||
| from synapse.rest.client.v1 import login, room | ||||
| from synapse.rest.client.v2_alpha import report_event | ||||
| 
 | ||||
| from tests import unittest | ||||
| 
 | ||||
| 
 | ||||
| class ReportEventTestCase(unittest.HomeserverTestCase): | ||||
|     servlets = [ | ||||
|         synapse.rest.admin.register_servlets, | ||||
|         login.register_servlets, | ||||
|         room.register_servlets, | ||||
|         report_event.register_servlets, | ||||
|     ] | ||||
| 
 | ||||
|     def prepare(self, reactor, clock, hs): | ||||
|         self.admin_user = self.register_user("admin", "pass", admin=True) | ||||
|         self.admin_user_tok = self.login("admin", "pass") | ||||
|         self.other_user = self.register_user("user", "pass") | ||||
|         self.other_user_tok = self.login("user", "pass") | ||||
| 
 | ||||
|         self.room_id = self.helper.create_room_as( | ||||
|             self.other_user, tok=self.other_user_tok, is_public=True | ||||
|         ) | ||||
|         self.helper.join(self.room_id, user=self.admin_user, tok=self.admin_user_tok) | ||||
|         resp = self.helper.send(self.room_id, tok=self.admin_user_tok) | ||||
|         self.event_id = resp["event_id"] | ||||
|         self.report_path = "rooms/{}/report/{}".format(self.room_id, self.event_id) | ||||
| 
 | ||||
|     def test_reason_str_and_score_int(self): | ||||
|         data = {"reason": "this makes me sad", "score": -100} | ||||
|         self._assert_status(200, data) | ||||
| 
 | ||||
|     def test_no_reason(self): | ||||
|         data = {"score": 0} | ||||
|         self._assert_status(200, data) | ||||
| 
 | ||||
|     def test_no_score(self): | ||||
|         data = {"reason": "this makes me sad"} | ||||
|         self._assert_status(200, data) | ||||
| 
 | ||||
|     def test_no_reason_and_no_score(self): | ||||
|         data = {} | ||||
|         self._assert_status(200, data) | ||||
| 
 | ||||
|     def test_reason_int_and_score_str(self): | ||||
|         data = {"reason": 10, "score": "string"} | ||||
|         self._assert_status(400, data) | ||||
| 
 | ||||
|     def test_reason_zero_and_score_blank(self): | ||||
|         data = {"reason": 0, "score": ""} | ||||
|         self._assert_status(400, data) | ||||
| 
 | ||||
|     def test_reason_and_score_null(self): | ||||
|         data = {"reason": None, "score": None} | ||||
|         self._assert_status(400, data) | ||||
| 
 | ||||
|     def _assert_status(self, response_status, data): | ||||
|         channel = self.make_request( | ||||
|             "POST", | ||||
|             self.report_path, | ||||
|             json.dumps(data), | ||||
|             access_token=self.other_user_tok, | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             response_status, int(channel.result["code"]), msg=channel.result["body"] | ||||
|         ) | ||||
		Loading…
	
		Reference in New Issue
	
	 Callum Brown
						Callum Brown