def test_thumbnail_repeated_thumbnail(self): """Test that fetching the same thumbnail works, and deleting the on disk thumbnail regenerates it. """ self._test_thumbnail( "scale", self.test_image.expected_scaled, self.test_image.expected_found ) if not self.test_image.expected_found: return # Fetching again should work, without re-requesting the image from the # remote. params = "?width=32&height=32&method=scale" channel = make_request( self.reactor, FakeSite(self.thumbnail_resource), "GET", self.media_id + params, shorthand=False, await_result=False, ) self.pump() self.assertEqual(channel.code, 200) if self.test_image.expected_scaled: self.assertEqual( channel.result["body"], self.test_image.expected_scaled, channel.result["body"], ) # Deleting the thumbnail on disk then re-requesting it should work as # Synapse should regenerate missing thumbnails. origin, media_id = self.media_id.split("/") info = self.get_success(self.store.get_cached_remote_media(origin, media_id)) file_id = info["filesystem_id"] thumbnail_dir = self.media_repo.filepaths.remote_media_thumbnail_dir( origin, file_id ) shutil.rmtree(thumbnail_dir, ignore_errors=True) channel = make_request( self.reactor, FakeSite(self.thumbnail_resource), "GET", self.media_id + params, shorthand=False, await_result=False, ) self.pump() self.assertEqual(channel.code, 200) if self.test_image.expected_scaled: self.assertEqual( channel.result["body"], self.test_image.expected_scaled, channel.result["body"], )
def _validate_token(self, link): # Remove the host path = link.replace("https://example.com", "") # Load the password reset confirmation page channel = make_request( self.reactor, FakeSite(self.submit_token_resource), "GET", path, shorthand=False, ) self.assertEquals(200, channel.code, channel.result) # Now POST to the same endpoint, mimicking the same behaviour as clicking the # password reset confirm button # Confirm the password reset channel = make_request( self.reactor, FakeSite(self.submit_token_resource), "POST", path, content=b"", shorthand=False, content_is_form=True, ) self.assertEquals(200, channel.code, channel.result)
def test_accept_consent(self): """ A user can use the consent form to accept the terms. """ uri_builder = ConsentURIBuilder(self.hs.config) resource = consent_resource.ConsentResource(self.hs) # Register a user user_id = self.register_user("user", "pass") access_token = self.login("user", "pass") # Fetch the consent page, to get the consent version consent_uri = ( uri_builder.build_user_consent_uri(user_id).replace("_matrix/", "") + "&u=user" ) channel = make_request( self.reactor, FakeSite(resource, self.reactor), "GET", consent_uri, access_token=access_token, shorthand=False, ) self.assertEqual(channel.code, 200) # Get the version from the body, and whether we've consented version, consented = channel.result["body"].decode("ascii").split(",") self.assertEqual(consented, "False") # POST to the consent page, saying we've agreed channel = make_request( self.reactor, FakeSite(resource, self.reactor), "POST", consent_uri + "&v=" + version, access_token=access_token, shorthand=False, ) self.assertEqual(channel.code, 200) # Fetch the consent page, to get the consent version -- it should have # changed channel = make_request( self.reactor, FakeSite(resource, self.reactor), "GET", consent_uri, access_token=access_token, shorthand=False, ) self.assertEqual(channel.code, 200) # Get the version from the body, and check that it's the version we # agreed to, and that we've consented to it. version, consented = channel.result["body"].decode("ascii").split(",") self.assertEqual(consented, "True") self.assertEqual(version, "1")
def upload_media( self, resource: Resource, image_data: bytes, tok: str, filename: str = "test.png", expect_code: int = 200, ) -> dict: """Upload a piece of test media to the media repo Args: resource: The resource that will handle the upload request image_data: The image data to upload tok: The user token to use during the upload filename: The filename of the media to be uploaded expect_code: The return code to expect from attempting to upload the media """ image_length = len(image_data) path = "/_matrix/media/r0/upload?filename=%s" % (filename, ) _, channel = make_request( self.hs.get_reactor(), FakeSite(resource), "POST", path, content=image_data, access_token=tok, custom_headers=[(b"Content-Length", str(image_length))], ) assert channel.code == expect_code, "Expected: %d, got: %d, resp: %r" % ( expect_code, int(channel.result["code"]), channel.result["body"], ) return channel.json_body
def test_callback_indirect_exception(self) -> None: """ If the web callback raises an uncaught exception in a Deferred, it will be translated into a 500. """ def _throw(*args: object) -> NoReturn: raise Exception("boo") def _callback(request: SynapseRequest, **kwargs: object) -> "Deferred[None]": d: "Deferred[None]" = Deferred() d.addCallback(_throw) self.reactor.callLater(0.5, d.callback, True) return make_deferred_yieldable(d) res = JsonResource(self.homeserver) res.register_paths( "GET", [re.compile("^/_matrix/foo$")], _callback, "test_servlet" ) channel = make_request( self.reactor, FakeSite(res, self.reactor), b"GET", b"/_matrix/foo" ) self.assertEqual(channel.result["code"], b"500")
def _req(self, content_disposition): channel = make_request( self.reactor, FakeSite(self.download_resource, self.reactor), "GET", self.media_id, shorthand=False, await_result=False, ) self.pump() # We've made one fetch, to example.com, using the media URL, and asking # the other server not to do a remote fetch self.assertEqual(len(self.fetches), 1) self.assertEqual(self.fetches[0][1], "example.com") self.assertEqual(self.fetches[0][2], "/_matrix/media/r0/download/" + self.media_id) self.assertEqual(self.fetches[0][3], {"allow_remote": "false"}) headers = { b"Content-Length": [b"%d" % (len(self.test_image.data))], b"Content-Type": [self.test_image.content_type], } if content_disposition: headers[b"Content-Disposition"] = [content_disposition] self.fetches[0][0].callback( (self.test_image.data, (len(self.test_image.data), headers))) self.pump() self.assertEqual(channel.code, 200) return channel
def test_head_request(self) -> None: """ JsonResource.handler_for_request gives correctly decoded URL args to the callback, while Twisted will give the raw bytes of URL query arguments. """ def _callback( request: SynapseRequest, **kwargs: object ) -> Tuple[int, Dict[str, object]]: return 200, {"result": True} res = JsonResource(self.homeserver) res.register_paths( "GET", [re.compile("^/_matrix/foo$")], _callback, "test_servlet", ) # The path was registered as GET, but this is a HEAD request. channel = make_request( self.reactor, FakeSite(res, self.reactor), b"HEAD", b"/_matrix/foo" ) self.assertEqual(channel.result["code"], b"200") self.assertNotIn("body", channel.result)
def test_handler_for_request(self): """ JsonResource.handler_for_request gives correctly decoded URL args to the callback, while Twisted will give the raw bytes of URL query arguments. """ got_kwargs = {} def _callback(request, **kwargs): got_kwargs.update(kwargs) return 200, kwargs res = JsonResource(self.homeserver) res.register_paths( "GET", [re.compile("^/_matrix/foo/(?P<room_id>[^/]*)$")], _callback, "test_servlet", ) request, channel = make_request(self.reactor, FakeSite(res), b"GET", b"/_matrix/foo/%E2%98%83?a=%E2%98%83") self.assertEqual(request.args, {b"a": ["\N{SNOWMAN}".encode("utf8")]}) self.assertEqual(got_kwargs, {"room_id": "\N{SNOWMAN}"})
def test_handler_for_request(self) -> None: """ JsonResource.handler_for_request gives correctly decoded URL args to the callback, while Twisted will give the raw bytes of URL query arguments. """ got_kwargs = {} def _callback( request: SynapseRequest, **kwargs: object ) -> Tuple[int, Dict[str, object]]: got_kwargs.update(kwargs) return 200, kwargs res = JsonResource(self.homeserver) res.register_paths( "GET", [re.compile("^/_matrix/foo/(?P<room_id>[^/]*)$")], _callback, "test_servlet", ) make_request( self.reactor, FakeSite(res, self.reactor), b"GET", b"/_matrix/foo/%E2%98%83?a=%E2%98%83", ) self.assertEqual(got_kwargs, {"room_id": "\N{SNOWMAN}"})
def test_sync(self): handler = _SyncTestCustomEndpoint({}, None).handle_request resource = AdditionalResource(self.hs, handler) channel = make_request(self.reactor, FakeSite(resource), "GET", "/") self.assertEqual(channel.code, 200) self.assertEqual(channel.json_body, {"some_key": "some_value_sync"})
def test_render_public_consent(self): """You can observe the terms form without specifying a user""" resource = consent_resource.ConsentResource(self.hs) channel = make_request(self.reactor, FakeSite(resource), "GET", "/consent?v=1", shorthand=False) self.assertEqual(channel.code, 200)
def test_head_request(self): """A head request should work by being turned into a GET request.""" async def callback(request): request.write(b"response") request.finish() res = WrapHtmlRequestHandlerTests.TestResource() res.callback = callback channel = make_request(self.reactor, FakeSite(res), b"HEAD", b"/path") self.assertEqual(channel.result["code"], b"200") self.assertNotIn("body", channel.result)
def test_good_response(self): async def callback(request): request.write(b"response") request.finish() res = WrapHtmlRequestHandlerTests.TestResource() res.callback = callback channel = make_request(self.reactor, FakeSite(res), b"GET", b"/path") self.assertEqual(channel.result["code"], b"200") body = channel.result["body"] self.assertEqual(body, b"response")
def _validate_token(self, link): # Remove the host path = link.replace("https://example.com", "") # Load the password reset confirmation page request, channel = make_request( self.reactor, FakeSite(self.submit_token_resource), "GET", path, shorthand=False, ) self.assertEquals(200, channel.code, channel.result) # Now POST to the same endpoint, mimicking the same behaviour as clicking the # password reset confirm button # Send arguments as url-encoded form data, matching the template's behaviour form_args = [] for key, value_list in request.args.items(): for value in value_list: arg = (key, value) form_args.append(arg) # Confirm the password reset request, channel = make_request( self.reactor, FakeSite(self.submit_token_resource), "POST", path, content=urlencode(form_args).encode("utf8"), shorthand=False, content_is_form=True, ) self.assertEquals(200, channel.code, channel.result)
def test_callback_direct_exception(self): """ If the web callback raises an uncaught exception, it will be translated into a 500. """ def _callback(request, **kwargs): raise Exception("boo") res = JsonResource(self.homeserver) res.register_paths("GET", [re.compile("^/_matrix/foo$")], _callback, "test_servlet") channel = make_request(self.reactor, FakeSite(res, self.reactor), b"GET", b"/_matrix/foo") self.assertEqual(channel.result["code"], b"500")
def test_redirect_exception(self): """ If the callback raises a RedirectException, it is turned into a 30x with the right location. """ async def callback(request, **kwargs): raise RedirectException(b"/look/an/eagle", 301) res = WrapHtmlRequestHandlerTests.TestResource() res.callback = callback channel = make_request(self.reactor, FakeSite(res), b"GET", b"/path") self.assertEqual(channel.result["code"], b"301") headers = channel.result["headers"] location_headers = [v for k, v in headers if k == b"Location"] self.assertEqual(location_headers, [b"/look/an/eagle"])
def test_quarantine_media_by_id(self) -> None: self.register_user("id_admin", "pass", admin=True) admin_user_tok = self.login("id_admin", "pass") self.register_user("id_nonadmin", "pass", admin=False) non_admin_user_tok = self.login("id_nonadmin", "pass") # Upload some media into the room response = self.helper.upload_media(self.upload_resource, SMALL_PNG, tok=admin_user_tok) # Extract media ID from the response server_name_and_media_id = response["content_uri"][ 6:] # Cut off 'mxc://' server_name, media_id = server_name_and_media_id.split("/") # Attempt to access the media channel = make_request( self.reactor, FakeSite(self.download_resource, self.reactor), "GET", server_name_and_media_id, shorthand=False, access_token=non_admin_user_tok, ) # Should be successful self.assertEqual(HTTPStatus.OK, channel.code) # Quarantine the media url = "/_synapse/admin/v1/media/quarantine/%s/%s" % ( urllib.parse.quote(server_name), urllib.parse.quote(media_id), ) channel = self.make_request( "POST", url, access_token=admin_user_tok, ) self.pump(1.0) self.assertEqual(HTTPStatus.OK, channel.code, msg=channel.json_body) # Attempt to access the media self._ensure_quarantined(admin_user_tok, server_name_and_media_id)
def _test_thumbnail(self, method: str, expected_body: Optional[bytes], expected_found: bool) -> None: params = "?width=32&height=32&method=" + method channel = make_request( self.reactor, FakeSite(self.thumbnail_resource, self.reactor), "GET", self.media_id + params, shorthand=False, await_result=False, ) self.pump() headers = { b"Content-Length": [b"%d" % (len(self.test_image.data))], b"Content-Type": [self.test_image.content_type], } self.fetches[0][0].callback( (self.test_image.data, (len(self.test_image.data), headers))) self.pump() if expected_found: self.assertEqual(channel.code, 200) self.assertEqual( channel.headers.getRawHeaders(b"Cross-Origin-Resource-Policy"), [b"cross-origin"], ) if expected_body is not None: self.assertEqual(channel.result["body"], expected_body, channel.result["body"]) else: # ensure that the result is at least some valid image Image.open(BytesIO(channel.result["body"])) else: # A 404 with a JSON body. self.assertEqual(channel.code, 404) self.assertEqual( channel.json_body, { "errcode": "M_NOT_FOUND", "error": "Not found [b'example.com', b'12345']", }, )
def _ensure_quarantined(self, admin_user_tok, server_and_media_id): """Ensure a piece of media is quarantined when trying to access it.""" channel = make_request( self.reactor, FakeSite(self.download_resource), "GET", server_and_media_id, shorthand=False, access_token=admin_user_tok, ) # Should be quarantined self.assertEqual( 404, int(channel.code), msg=("Expected to receive a 404 on accessing quarantined media: %s" % server_and_media_id), )
def test_callback_synapseerror(self): """ If the web callback raises a SynapseError, it returns the appropriate status code and message set in it. """ def _callback(request, **kwargs): raise SynapseError(403, "Forbidden!!one!", Codes.FORBIDDEN) res = JsonResource(self.homeserver) res.register_paths("GET", [re.compile("^/_matrix/foo$")], _callback, "test_servlet") channel = make_request(self.reactor, FakeSite(res, self.reactor), b"GET", b"/_matrix/foo") self.assertEqual(channel.result["code"], b"403") self.assertEqual(channel.json_body["error"], "Forbidden!!one!") self.assertEqual(channel.json_body["errcode"], "M_FORBIDDEN")
def test_no_handler(self): """ If there is no handler to process the request, Synapse will return 400. """ def _callback(request, **kwargs): """ Not ever actually called! """ self.fail("shouldn't ever get here") res = JsonResource(self.homeserver) res.register_paths("GET", [re.compile("^/_matrix/foo$")], _callback, "test_servlet") channel = make_request(self.reactor, FakeSite(res, self.reactor), b"GET", b"/_matrix/foobar") self.assertEqual(channel.result["code"], b"400") self.assertEqual(channel.json_body["error"], "Unrecognized request") self.assertEqual(channel.json_body["errcode"], "M_UNRECOGNIZED")
def _ensure_quarantined(self, admin_user_tok: str, server_and_media_id: str) -> None: """Ensure a piece of media is quarantined when trying to access it.""" channel = make_request( self.reactor, FakeSite(self.download_resource, self.reactor), "GET", server_and_media_id, shorthand=False, access_token=admin_user_tok, ) # Should be quarantined self.assertEqual( HTTPStatus.NOT_FOUND, channel.code, msg= ("Expected to receive a HTTPStatus.NOT_FOUND on accessing quarantined media: %s" % server_and_media_id), )
def test_redirect_exception_with_cookie(self): """ If the callback raises a RedirectException which sets a cookie, that is returned too """ async def callback(request, **kwargs): e = RedirectException(b"/no/over/there", 304) e.cookies.append(b"session=yespls") raise e res = WrapHtmlRequestHandlerTests.TestResource() res.callback = callback channel = make_request(self.reactor, FakeSite(res), b"GET", b"/path") self.assertEqual(channel.result["code"], b"304") headers = channel.result["headers"] location_headers = [v for k, v in headers if k == b"Location"] self.assertEqual(location_headers, [b"/no/over/there"]) cookies_headers = [v for k, v in headers if k == b"Set-Cookie"] self.assertEqual(cookies_headers, [b"session=yespls"])
def _access_media(self, server_and_media_id, expect_success=True): """ Try to access a media and check the result """ download_resource = self.media_repo.children[b"download"] media_id = server_and_media_id.split("/")[1] local_path = self.filepaths.local_media_filepath(media_id) channel = make_request( self.reactor, FakeSite(download_resource), "GET", server_and_media_id, shorthand=False, access_token=self.admin_user_tok, ) if expect_success: self.assertEqual( 200, channel.code, msg=( "Expected to receive a 200 on accessing media: %s" % server_and_media_id ), ) # Test that the file exists self.assertTrue(os.path.exists(local_path)) else: self.assertEqual( 404, channel.code, msg=( "Expected to receive a 404 on accessing deleted media: %s" % (server_and_media_id) ), ) # Test that the file is deleted self.assertFalse(os.path.exists(local_path))
def setUp(self) -> None: self.reactor = ThreadedMemoryReactorClock() self.clock = Clock(self.reactor) self.resource = CancellableDirectServeHtmlResource(self.clock) self.site = FakeSite(self.resource, self.reactor)
def test_cannot_quarantine_safe_media(self): self.register_user("user_admin", "pass", admin=True) admin_user_tok = self.login("user_admin", "pass") non_admin_user = self.register_user("user_nonadmin", "pass", admin=False) non_admin_user_tok = self.login("user_nonadmin", "pass") # Upload some media response_1 = self.helper.upload_media(self.upload_resource, self.image_data, tok=non_admin_user_tok) response_2 = self.helper.upload_media(self.upload_resource, self.image_data, tok=non_admin_user_tok) # Extract media IDs server_and_media_id_1 = response_1["content_uri"][6:] server_and_media_id_2 = response_2["content_uri"][6:] # Mark the second item as safe from quarantine. _, media_id_2 = server_and_media_id_2.split("/") self.get_success(self.store.mark_local_media_as_safe(media_id_2)) # Quarantine all media by this user url = "/_synapse/admin/v1/user/%s/media/quarantine" % urllib.parse.quote( non_admin_user) request, channel = self.make_request( "POST", url.encode("ascii"), access_token=admin_user_tok, ) self.pump(1.0) self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"]) self.assertEqual( json.loads(channel.result["body"].decode("utf-8")), {"num_quarantined": 1}, "Expected 1 quarantined item", ) # Attempt to access each piece of media, the first should fail, the # second should succeed. self._ensure_quarantined(admin_user_tok, server_and_media_id_1) # Attempt to access each piece of media request, channel = make_request( self.reactor, FakeSite(self.download_resource), "GET", server_and_media_id_2, shorthand=False, access_token=non_admin_user_tok, ) # Shouldn't be quarantined self.assertEqual( 200, int(channel.code), msg= ("Expected to receive a 200 on accessing not-quarantined media: %s" % server_and_media_id_2), )
def test_delete_media(self) -> None: """ Tests that delete a media is successfully """ download_resource = self.media_repo.children[b"download"] upload_resource = self.media_repo.children[b"upload"] # Upload some media into the room response = self.helper.upload_media( upload_resource, SMALL_PNG, tok=self.admin_user_tok, expect_code=HTTPStatus.OK, ) # Extract media ID from the response server_and_media_id = response["content_uri"][6:] # Cut off 'mxc://' server_name, media_id = server_and_media_id.split("/") self.assertEqual(server_name, self.server_name) # Attempt to access media channel = make_request( self.reactor, FakeSite(download_resource, self.reactor), "GET", server_and_media_id, shorthand=False, access_token=self.admin_user_tok, ) # Should be successful self.assertEqual( HTTPStatus.OK, channel.code, msg=("Expected to receive a HTTPStatus.OK on accessing media: %s" % server_and_media_id), ) # Test if the file exists local_path = self.filepaths.local_media_filepath(media_id) self.assertTrue(os.path.exists(local_path)) url = "/_synapse/admin/v1/media/%s/%s" % (self.server_name, media_id) # Delete media channel = self.make_request( "DELETE", url, access_token=self.admin_user_tok, ) self.assertEqual(HTTPStatus.OK, channel.code, msg=channel.json_body) self.assertEqual(1, channel.json_body["total"]) self.assertEqual( media_id, channel.json_body["deleted_media"][0], ) # Attempt to access media channel = make_request( self.reactor, FakeSite(download_resource, self.reactor), "GET", server_and_media_id, shorthand=False, access_token=self.admin_user_tok, ) self.assertEqual( HTTPStatus.NOT_FOUND, channel.code, msg= ("Expected to receive a HTTPStatus.NOT_FOUND on accessing deleted media: %s" % server_and_media_id), ) # Test if the file is deleted self.assertFalse(os.path.exists(local_path))
def _get_media_req( self, hs: HomeServer, target: str, media_id: str ) -> Tuple[FakeChannel, Request]: """Request some remote media from the given HS by calling the download API. This then triggers an outbound request from the HS to the target. Returns: The channel for the *client* request and the *outbound* request for the media which the caller should respond to. """ resource = hs.get_media_repository_resource().children[b"download"] channel = make_request( self.reactor, FakeSite(resource), "GET", "/{}/{}".format(target, media_id), shorthand=False, access_token=self.access_token, await_result=False, ) self.pump() clients = self.reactor.tcpClients self.assertGreaterEqual(len(clients), 1) (host, port, client_factory, _timeout, _bindAddress) = clients.pop() # build the test server server_tls_protocol = _build_test_server(get_connection_factory()) # now, tell the client protocol factory to build the client protocol (it will be a # _WrappingProtocol, around a TLSMemoryBIOProtocol, around an # HTTP11ClientProtocol) and wire the output of said protocol up to the server via # a FakeTransport. # # Normally this would be done by the TCP socket code in Twisted, but we are # stubbing that out here. client_protocol = client_factory.buildProtocol(None) client_protocol.makeConnection( FakeTransport(server_tls_protocol, self.reactor, client_protocol) ) # tell the server tls protocol to send its stuff back to the client, too server_tls_protocol.makeConnection( FakeTransport(client_protocol, self.reactor, server_tls_protocol) ) # fish the test server back out of the server-side TLS protocol. http_server = server_tls_protocol.wrappedProtocol # give the reactor a pump to get the TLS juices flowing. self.reactor.pump((0.1,)) self.assertEqual(len(http_server.requests), 1) request = http_server.requests[0] self.assertEqual(request.method, b"GET") self.assertEqual( request.path, "/_matrix/media/r0/download/{}/{}".format(target, media_id).encode("utf-8"), ) self.assertEqual( request.requestHeaders.getRawHeaders(b"host"), [target.encode("utf-8")] ) return channel, request
def test_delete_media(self): """ Tests that delete a media is successfully """ download_resource = self.media_repo.children[b"download"] upload_resource = self.media_repo.children[b"upload"] image_data = unhexlify( b"89504e470d0a1a0a0000000d4948445200000001000000010806" b"0000001f15c4890000000a49444154789c63000100000500010d" b"0a2db40000000049454e44ae426082" ) # Upload some media into the room response = self.helper.upload_media( upload_resource, image_data, tok=self.admin_user_tok, expect_code=200 ) # Extract media ID from the response server_and_media_id = response["content_uri"][6:] # Cut off 'mxc://' server_name, media_id = server_and_media_id.split("/") self.assertEqual(server_name, self.server_name) # Attempt to access media channel = make_request( self.reactor, FakeSite(download_resource), "GET", server_and_media_id, shorthand=False, access_token=self.admin_user_tok, ) # Should be successful self.assertEqual( 200, channel.code, msg=( "Expected to receive a 200 on accessing media: %s" % server_and_media_id ), ) # Test if the file exists local_path = self.filepaths.local_media_filepath(media_id) self.assertTrue(os.path.exists(local_path)) url = "/_synapse/admin/v1/media/%s/%s" % (self.server_name, media_id) # Delete media channel = self.make_request( "DELETE", url, access_token=self.admin_user_tok, ) self.assertEqual(200, channel.code, msg=channel.json_body) self.assertEqual(1, channel.json_body["total"]) self.assertEqual( media_id, channel.json_body["deleted_media"][0], ) # Attempt to access media channel = make_request( self.reactor, FakeSite(download_resource), "GET", server_and_media_id, shorthand=False, access_token=self.admin_user_tok, ) self.assertEqual( 404, channel.code, msg=( "Expected to receive a 404 on accessing deleted media: %s" % server_and_media_id ), ) # Test if the file is deleted self.assertFalse(os.path.exists(local_path))
def test_cannot_quarantine_safe_media(self) -> None: self.register_user("user_admin", "pass", admin=True) admin_user_tok = self.login("user_admin", "pass") non_admin_user = self.register_user("user_nonadmin", "pass", admin=False) non_admin_user_tok = self.login("user_nonadmin", "pass") # Upload some media response_1 = self.helper.upload_media(self.upload_resource, SMALL_PNG, tok=non_admin_user_tok) response_2 = self.helper.upload_media(self.upload_resource, SMALL_PNG, tok=non_admin_user_tok) # Extract media IDs server_and_media_id_1 = response_1["content_uri"][6:] server_and_media_id_2 = response_2["content_uri"][6:] # Mark the second item as safe from quarantine. _, media_id_2 = server_and_media_id_2.split("/") # Quarantine the media url = "/_synapse/admin/v1/media/protect/%s" % ( urllib.parse.quote(media_id_2), ) channel = self.make_request("POST", url, access_token=admin_user_tok) self.pump(1.0) self.assertEqual(HTTPStatus.OK, channel.code, msg=channel.json_body) # Quarantine all media by this user url = "/_synapse/admin/v1/user/%s/media/quarantine" % urllib.parse.quote( non_admin_user) channel = self.make_request( "POST", url.encode("ascii"), access_token=admin_user_tok, ) self.pump(1.0) self.assertEqual(HTTPStatus.OK, channel.code, msg=channel.json_body) self.assertEqual(channel.json_body, {"num_quarantined": 1}, "Expected 1 quarantined item") # Attempt to access each piece of media, the first should fail, the # second should succeed. self._ensure_quarantined(admin_user_tok, server_and_media_id_1) # Attempt to access each piece of media channel = make_request( self.reactor, FakeSite(self.download_resource, self.reactor), "GET", server_and_media_id_2, shorthand=False, access_token=non_admin_user_tok, ) # Shouldn't be quarantined self.assertEqual( HTTPStatus.OK, channel.code, msg= ("Expected to receive a HTTPStatus.OK on accessing not-quarantined media: %s" % server_and_media_id_2), )