예제 #1
0
    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"],
            )
예제 #2
0
    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)
예제 #3
0
    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")
예제 #4
0
파일: utils.py 프로젝트: yunwah/synapse
    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
예제 #5
0
    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")
예제 #6
0
    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
예제 #7
0
    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)
예제 #8
0
    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}"})
예제 #9
0
    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}"})
예제 #10
0
    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"})
예제 #11
0
 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)
예제 #12
0
    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)
예제 #13
0
    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")
예제 #14
0
    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)
예제 #15
0
    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")
예제 #16
0
    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"])
예제 #17
0
    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)
예제 #18
0
    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']",
                },
            )
예제 #19
0
    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),
        )
예제 #20
0
    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")
예제 #21
0
    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")
예제 #22
0
    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),
        )
예제 #23
0
    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"])
예제 #24
0
    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))
예제 #25
0
 def setUp(self) -> None:
     self.reactor = ThreadedMemoryReactorClock()
     self.clock = Clock(self.reactor)
     self.resource = CancellableDirectServeHtmlResource(self.clock)
     self.site = FakeSite(self.resource, self.reactor)
예제 #26
0
    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),
        )
예제 #27
0
    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
예제 #29
0
    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))
예제 #30
0
    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),
        )