mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-08-27 12:30:13 +03:00
Merge pull request #2860 from yueguobin/feat/project-gns3file-endpoint
api: serve the project .gns3 topology file
This commit is contained in:
commit
006102c1af
File diff suppressed because one or more lines are too long
@ -746,6 +746,21 @@ async def get_file(file_path: str, project: Project = Depends(dep_project)) -> F
|
||||
return FileResponse(path, media_type="application/octet-stream")
|
||||
|
||||
|
||||
@router.get("/{project_id}/gns3file", dependencies=[Depends(has_privilege("Project.Audit"))])
|
||||
async def get_project_gns3_file(project: Project = Depends(dep_project)) -> FileResponse:
|
||||
"""
|
||||
Return the .gns3 topology file of a project.
|
||||
|
||||
Required privilege: Project.Audit
|
||||
"""
|
||||
|
||||
path = project.topology_file
|
||||
if not os.path.exists(path):
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
|
||||
|
||||
return FileResponse(path, media_type="application/json")
|
||||
|
||||
|
||||
@router.post(
|
||||
"/{project_id}/files/{file_path:path}",
|
||||
status_code=status.HTTP_204_NO_CONTENT,
|
||||
|
||||
@ -1685,6 +1685,14 @@ class Project:
|
||||
def _topology_file(self):
|
||||
return os.path.join(self.path, self._filename)
|
||||
|
||||
@property
|
||||
def topology_file(self):
|
||||
"""
|
||||
Absolute path of the .gns3 topology file
|
||||
"""
|
||||
|
||||
return self._topology_file()
|
||||
|
||||
@locking
|
||||
async def open(self, auto_start=True):
|
||||
"""
|
||||
|
||||
@ -435,8 +435,43 @@ class TestControllerProjectRoutes:
|
||||
|
||||
response = await client.get(app.url_path_for("get_file", project_id=project.id, file_path="../hello"))
|
||||
assert response.status_code == status.HTTP_404_NOT_FOUND
|
||||
|
||||
|
||||
|
||||
|
||||
async def test_get_project_gns3_file(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
|
||||
|
||||
response = await client.get(app.url_path_for("get_project_gns3_file", project_id=project.id))
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
assert response.headers["content-type"].startswith("application/json")
|
||||
topology = response.json()
|
||||
assert topology["name"] == "test"
|
||||
assert "topology" in topology
|
||||
|
||||
|
||||
async def test_get_project_gns3_file_raw_content(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
|
||||
|
||||
# the endpoint must serve the raw file content, without the project being opened
|
||||
topology = {
|
||||
"name": "test",
|
||||
"topology": {
|
||||
"nodes": [{"node_id": "abc", "name": "n1", "x": 10, "y": 20}],
|
||||
"links": [],
|
||||
"drawings": [{"drawing_id": "def", "svg": "<svg/>"}],
|
||||
},
|
||||
}
|
||||
with open(project.topology_file, "w+") as f:
|
||||
json.dump(topology, f)
|
||||
|
||||
response = await client.get(app.url_path_for("get_project_gns3_file", project_id=project.id))
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
assert response.json() == topology
|
||||
|
||||
|
||||
async def test_get_project_gns3_file_project_not_found(self, app: FastAPI, client: AsyncClient) -> None:
|
||||
|
||||
response = await client.get(app.url_path_for("get_project_gns3_file", project_id=str(uuid.uuid4())))
|
||||
assert response.status_code == status.HTTP_404_NOT_FOUND
|
||||
|
||||
|
||||
async def test_get_file_forbidden_location(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
|
||||
|
||||
file_path = "foo/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user