diff --git a/CHANGELOG.md b/CHANGELOG.md index cc52a197..ce366d26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed a bug where the red agent acted to early - Fixed the order of service health state - Fixed an issue where starting a node didn't start the services on it +- Added support for SQL INSERT command. diff --git a/docs/source/simulation_components/system/database_client_server.rst b/docs/source/simulation_components/system/database_client_server.rst index 0b0dcc8e..07912f3e 100644 --- a/docs/source/simulation_components/system/database_client_server.rst +++ b/docs/source/simulation_components/system/database_client_server.rst @@ -17,7 +17,7 @@ Key capabilities - Creates a database file in the ``Node`` 's ``FileSystem`` upon creation. - Handles connecting clients by maintaining a dictionary of connections mapped to session IDs. - Authenticates connections using a configurable password. -- Simulates ``SELECT`` and ``DELETE`` SQL queries. +- Simulates ``SELECT``, ``DELETE`` and ``INSERT`` SQL queries. - Returns query results and status codes back to clients. - Leverages the Service base class for install/uninstall, status tracking, etc. diff --git a/src/primaite/simulator/system/services/database/database_service.py b/src/primaite/simulator/system/services/database/database_service.py index d75b4424..0b9554d5 100644 --- a/src/primaite/simulator/system/services/database/database_service.py +++ b/src/primaite/simulator/system/services/database/database_service.py @@ -189,7 +189,7 @@ class DatabaseService(Service): } def _process_sql( - self, query: Literal["SELECT", "DELETE"], query_id: str, connection_id: Optional[str] = None + self, query: Literal["SELECT", "DELETE", "INSERT"], query_id: str, connection_id: Optional[str] = None ) -> Dict[str, Union[int, List[Any]]]: """ Executes the given SQL query and returns the result. @@ -197,6 +197,7 @@ class DatabaseService(Service): Possible queries: - SELECT : returns the data - DELETE : deletes the data + - INSERT : inserts the data :param query: The SQL query to be executed. :return: Dictionary containing status code and data fetched. @@ -220,9 +221,27 @@ class DatabaseService(Service): return {"status_code": 404, "data": False} elif query == "DELETE": self.db_file.health_status = FileSystemItemHealthStatus.COMPROMISED - return {"status_code": 200, "type": "sql", "data": False, "uuid": query_id, "connection_id": connection_id} + return { + "status_code": 200, + "type": "sql", + "data": False, + "uuid": query_id, + "connection_id": connection_id, + } + elif query == "INSERT": + if self.health_state_actual == SoftwareHealthState.GOOD: + return { + "status_code": 200, + "type": "sql", + "data": False, + "uuid": query_id, + "connection_id": connection_id, + } + else: + return {"status_code": 404, "data": False} else: # Invalid query + self.sys_log.info(f"{self.name}: Invalid {query}") return {"status_code": 500, "data": False} def describe_state(self) -> Dict: diff --git a/tests/integration_tests/system/test_database_on_node.py b/tests/integration_tests/system/test_database_on_node.py index e015f9ee..ac0e65b4 100644 --- a/tests/integration_tests/system/test_database_on_node.py +++ b/tests/integration_tests/system/test_database_on_node.py @@ -101,6 +101,7 @@ def test_database_client_query(uc2_network): db_client.connect() assert db_client.query("SELECT") + assert db_client.query("INSERT") def test_create_database_backup(uc2_network): @@ -150,7 +151,7 @@ def test_database_client_cannot_query_offline_database_server(uc2_network): assert len(db_client.connections) assert db_client.query("SELECT") is True - + assert db_client.query("INSERT") is True db_server.power_off() for i in range(db_server.shut_down_duration + 1): @@ -160,3 +161,4 @@ def test_database_client_cannot_query_offline_database_server(uc2_network): assert db_service.operating_state is ServiceOperatingState.STOPPED assert db_client.query("SELECT") is False + assert db_client.query("INSERT") is False