diff --git a/gns3server/api/routes/controller/projects.py b/gns3server/api/routes/controller/projects.py index b8797e3c..9df7b9be 100644 --- a/gns3server/api/routes/controller/projects.py +++ b/gns3server/api/routes/controller/projects.py @@ -30,7 +30,7 @@ import logging log = logging.getLogger() -from fastapi import APIRouter, Depends, Request, Response, Body, HTTPException, status, WebSocket, WebSocketDisconnect +from fastapi import APIRouter, Depends, Request, Body, HTTPException, status, WebSocket, WebSocketDisconnect from fastapi.encoders import jsonable_encoder from fastapi.responses import StreamingResponse, FileResponse from websockets.exceptions import ConnectionClosed, WebSocketException @@ -395,6 +395,15 @@ async def duplicate_project( return new_project.asdict() +@router.get("/{project_id}/locked") +async def locked_project(project: Project = Depends(dep_project)) -> dict: + """ + Returns whether a project is locked or not + """ + + return {"result": project.locked} + + @router.post("/{project_id}/lock", status_code=status.HTTP_204_NO_CONTENT) async def lock_project(project: Project = Depends(dep_project)) -> None: """ diff --git a/gns3server/controller/project.py b/gns3server/controller/project.py index 37446cae..7107429a 100644 --- a/gns3server/controller/project.py +++ b/gns3server/controller/project.py @@ -1144,6 +1144,21 @@ class Project: self.emit_notification("node.updated", node.asdict()) self.dump() + @property + @open_required + def locked(self): + """ + Check if all items in a project are locked and not + """ + + for drawing in self._drawings.values(): + if not drawing.locked: + return False + for node in self.nodes.values(): + if not node.locked: + return False + return True + def dump(self): """ Dump topology to disk diff --git a/tests/api/routes/controller/test_projects.py b/tests/api/routes/controller/test_projects.py index e94cc8fc..7b392742 100644 --- a/tests/api/routes/controller/test_projects.py +++ b/tests/api/routes/controller/test_projects.py @@ -511,6 +511,10 @@ async def test_lock_unlock(app: FastAPI, client: AsyncClient, project: Project, for node in project.nodes.values(): assert node.locked is True + response = await client.get(app.url_path_for("locked_project", project_id=project.id)) + assert response.status_code == status.HTTP_200_OK + assert response.json()["result"] is True + response = await client.post(app.url_path_for("unlock_project", project_id=project.id)) assert response.status_code == status.HTTP_204_NO_CONTENT