From 23c48f5e3d581a071f9b32db5197e802cf4bb99d Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Thu, 24 Mar 2016 17:34:23 +0100 Subject: [PATCH] Add to project an API to write a file --- gns3server/handlers/api/project_handler.py | 40 ++++++++++++++++++++++ tests/handlers/api/test_project.py | 22 ++++++++++++ 2 files changed, 62 insertions(+) diff --git a/gns3server/handlers/api/project_handler.py b/gns3server/handlers/api/project_handler.py index 866fddf1..d918dd87 100644 --- a/gns3server/handlers/api/project_handler.py +++ b/gns3server/handlers/api/project_handler.py @@ -302,3 +302,43 @@ class ProjectHandler: raise aiohttp.web.HTTPNotFound() except PermissionError: raise aiohttp.web.HTTPForbidden + + @classmethod + @Route.post( + r"/projects/{project_id}/files/{path:.+}", + description="Get a file of a project", + parameters={ + "project_id": "The UUID of the project", + }, + raw=True, + status_codes={ + 200: "Return the file", + 403: "Permission denied", + 404: "The path doesn't exist" + }) + def write_file(request, response): + + pm = ProjectManager.instance() + project = pm.get_project(request.match_info["project_id"]) + path = request.match_info["path"] + path = os.path.normpath(path) + + # Raise error if user try to escape + if path[0] == ".": + raise aiohttp.web.HTTPForbidden + path = os.path.join(project.path, path) + + response.set_status(200) + + try: + with open(path, 'wb+') as f: + while True: + packet = yield from request.content.read(512) + if not packet: + break + f.write(packet) + + except FileNotFoundError: + raise aiohttp.web.HTTPNotFound() + except PermissionError: + raise aiohttp.web.HTTPForbidden diff --git a/tests/handlers/api/test_project.py b/tests/handlers/api/test_project.py index 5af3d03c..877593a6 100644 --- a/tests/handlers/api/test_project.py +++ b/tests/handlers/api/test_project.py @@ -261,3 +261,25 @@ def test_get_file(server, tmpdir): response = server.get("/projects/{project_id}/files/../hello".format(project_id=project.id), raw=True) assert response.status == 403 + + +def test_write_file(server, tmpdir): + + with patch("gns3server.config.Config.get_section_config", return_value={"project_directory": str(tmpdir)}): + project = ProjectManager.instance().create_project() + + with open(os.path.join(project.path, "hello"), "w+") as f: + f.write("world") + + response = server.post("/projects/{project_id}/files/hello".format(project_id=project.id), body="universe", raw=True) + assert response.status == 200 + + with open(os.path.join(project.path, "hello")) as f: + content = f.read() + assert content == "universe" + + response = server.post("/projects/{project_id}/files/test/false".format(project_id=project.id), body="universe", raw=True) + assert response.status == 404 + + response = server.post("/projects/{project_id}/files/../hello".format(project_id=project.id), body="universe", raw=True) + assert response.status == 403