diff --git a/server/lomas_server/routes_admin.py b/server/lomas_server/routes_admin.py index 7c0c7b52..345bdf0e 100644 --- a/server/lomas_server/routes_admin.py +++ b/server/lomas_server/routes_admin.py @@ -29,17 +29,19 @@ async def root(): # Get server state @router.get("/state", tags=["ADMIN_USER"]) async def get_state( + request: Request, user_name: str = Header(None), ) -> JSONResponse: """Returns the current state dict of this server instance. Args: + request (Request): Raw request object user_name (str, optional): The user name. Defaults to Header(None). Returns: JSONResponse: The state of the server instance. """ - from app import app # pylint: disable=C0415 + app = request.app return JSONResponse( content={ @@ -54,15 +56,16 @@ async def get_state( dependencies=[Depends(server_live)], tags=["ADMIN_USER"], ) -async def get_memory_usage() -> JSONResponse: +async def get_memory_usage(request: Request) -> JSONResponse: """Return the dataset store object memory usage Args: + request (Request): Raw request object user_name (str, optional): The user name. Defaults to Header(None). Returns: JSONResponse: with DatasetStore object memory usage """ - from app import app # pylint: disable=C0415 + app = request.app return JSONResponse( content={ @@ -78,7 +81,7 @@ async def get_memory_usage() -> JSONResponse: tags=["USER_METADATA"], ) def get_dataset_metadata( - _request: Request, + request: Request, query_json: GetDbData = Body(example_get_admin_db_data), user_name: str = Header(None), ) -> JSONResponse: @@ -100,7 +103,7 @@ def get_dataset_metadata( JSONResponse: The metadata dictionary for the specified dataset_name. """ - from app import app # pylint: disable=C0415 + app = request.app dataset_name = query_json.dataset_name if not app.state.admin_database.has_user_access_to_dataset( @@ -130,7 +133,7 @@ def get_dataset_metadata( tags=["USER_DUMMY"], ) def get_dummy_dataset( - _request: Request, + request: Request, query_json: GetDummyDataset = Body(example_get_dummy_dataset), user_name: str = Header(None), ) -> StreamingResponse: @@ -155,7 +158,7 @@ def get_dummy_dataset( Returns: StreamingResponse: a pd.DataFrame representing the dummy dataset. """ - from app import app # pylint: disable=C0415 + app = request.app dataset_name = query_json.dataset_name if not app.state.admin_database.has_user_access_to_dataset( @@ -188,7 +191,7 @@ def get_dummy_dataset( tags=["USER_BUDGET"], ) def get_initial_budget( - _request: Request, + request: Request, query_json: GetDbData = Body(example_get_admin_db_data), user_name: str = Header(None), ) -> JSONResponse: @@ -217,7 +220,7 @@ def get_initial_budget( - initial_epsilon (float): initial epsilon budget. - initial_delta (float): initial delta budget. """ - from app import app # pylint: disable=C0415 + app = request.app try: ( @@ -246,7 +249,7 @@ def get_initial_budget( tags=["USER_BUDGET"], ) def get_total_spent_budget( - _request: Request, + request: Request, query_json: GetDbData = Body(example_get_admin_db_data), user_name: str = Header(None), ) -> JSONResponse: @@ -275,7 +278,7 @@ def get_total_spent_budget( - total_spent_epsilon (float): total spent epsilon budget. - total_spent_delta (float): total spent delta budget. """ - from app import app # pylint: disable=C0415 + app = request.app try: ( @@ -304,7 +307,7 @@ def get_total_spent_budget( tags=["USER_BUDGET"], ) def get_remaining_budget( - _request: Request, + request: Request, query_json: GetDbData = Body(example_get_admin_db_data), user_name: str = Header(None), ) -> JSONResponse: @@ -333,7 +336,7 @@ def get_remaining_budget( - remaining_epsilon (float): remaining epsilon budget. - remaining_delta (float): remaining delta budget. """ - from app import app # pylint: disable=C0415 + app = request.app try: rem_epsilon, rem_delta = app.state.admin_database.get_remaining_budget( @@ -359,7 +362,7 @@ def get_remaining_budget( tags=["USER_BUDGET"], ) def get_user_previous_queries( - _request: Request, + request: Request, query_json: GetDbData = Body(example_get_admin_db_data), user_name: str = Header(None), ) -> JSONResponse: @@ -389,7 +392,7 @@ def get_user_previous_queries( - previous_queries (list[dict]): a list of dictionaries containing the previous queries. """ - from app import app # pylint: disable=C0415 + app = request.app try: previous_queries = app.state.admin_database.get_user_previous_queries( diff --git a/server/lomas_server/routes_dp.py b/server/lomas_server/routes_dp.py index a95f7b2f..68e59b2a 100644 --- a/server/lomas_server/routes_dp.py +++ b/server/lomas_server/routes_dp.py @@ -38,7 +38,7 @@ tags=["USER_QUERY"], ) def smartnoise_sql_handler( - _request: Request, + request: Request, query_json: SNSQLInp = Body(example_smartnoise_sql), user_name: str = Header(None), ) -> JSONResponse: @@ -84,7 +84,7 @@ def smartnoise_sql_handler( - spent_delta (float): The amount of delta budget spent for the query. """ - from app import app # pylint: disable=C0415 + app = request.app try: response = app.state.query_handler.handle_query( @@ -105,7 +105,7 @@ def smartnoise_sql_handler( tags=["USER_DUMMY"], ) def dummy_smartnoise_sql_handler( - _request: Request, + request: Request, query_json: DummySNSQLInp = Body(example_dummy_smartnoise_sql), user_name: str = Header(None), ) -> JSONResponse: @@ -147,7 +147,7 @@ def dummy_smartnoise_sql_handler( - query_response (pd.DataFrame): a DataFrame containing the query response. """ - from app import app # pylint: disable=C0415 + app = request.app dataset_name = query_json.dataset_name if not app.state.admin_database.has_user_access_to_dataset( @@ -181,7 +181,7 @@ def dummy_smartnoise_sql_handler( tags=["USER_QUERY"], ) def estimate_smartnoise_cost( - _request: Request, + request: Request, query_json: SNSQLInpCost = Body(example_smartnoise_sql_cost), user_name: str = Header(None), ) -> JSONResponse: @@ -214,7 +214,7 @@ def estimate_smartnoise_cost( - epsilon_cost (float): The estimated epsilon cost. - delta_cost (float): The estimated delta cost. """ - from app import app # pylint: disable=C0415 + app = request.app dataset_name = query_json.dataset_name if not app.state.admin_database.has_user_access_to_dataset( @@ -241,7 +241,7 @@ def estimate_smartnoise_cost( "/opendp_query", dependencies=[Depends(server_live)], tags=["USER_QUERY"] ) def opendp_query_handler( - _request: Request, + request: Request, query_json: OpenDPInp = Body(example_opendp), user_name: str = Header(None), ) -> JSONResponse: @@ -283,7 +283,7 @@ def opendp_query_handler( - spent_delta (float): The amount of delta budget spent for the query. """ - from app import app # pylint: disable=C0415 + app = request.app try: response = app.state.query_handler.handle_query( @@ -303,7 +303,7 @@ def opendp_query_handler( tags=["USER_DUMMY"], ) def dummy_opendp_query_handler( - _request: Request, + request: Request, query_json: DummyOpenDPInp = Body(example_dummy_opendp), user_name: str = Header(None), ) -> JSONResponse: @@ -342,7 +342,7 @@ def dummy_opendp_query_handler( - query_response (pd.DataFrame): a DataFrame containing the query response. """ - from app import app # pylint: disable=C0415 + app = request.app dataset_name = query_json.dataset_name if not app.state.admin_database.has_user_access_to_dataset( @@ -378,7 +378,7 @@ def dummy_opendp_query_handler( tags=["USER_QUERY"], ) def estimate_opendp_cost( - _request: Request, + request: Request, query_json: OpenDPInp = Body(example_opendp), user_name: str = Header(None), ) -> JSONResponse: @@ -405,7 +405,7 @@ def estimate_opendp_cost( - epsilon_cost (float): The estimated epsilon cost. - delta_cost (float): The estimated delta cost. """ - from app import app # pylint: disable=C0415 + app = request.app dataset_name = query_json.dataset_name if not app.state.admin_database.has_user_access_to_dataset( @@ -434,6 +434,7 @@ def estimate_opendp_cost( tags=["USER_QUERY"], ) def diffprivlib_query_handler( + request: Request, query_json: DiffPrivLibInp = Body(example_diffprivlib), user_name: str = Header(None), ): @@ -474,7 +475,7 @@ def diffprivlib_query_handler( - spent_delta (float): The amount of delta budget spent for the query. """ - from app import app # pylint: disable=C0415 + app = request.app try: response = app.state.query_handler.handle_query( @@ -494,6 +495,7 @@ def diffprivlib_query_handler( tags=["USER_DUMMY"], ) def dummy_diffprivlib_query_handler( + request: Request, query_json: DummyDiffPrivLibInp = Body(example_dummy_diffprivlib), user_name: str = Header(None), ): @@ -527,7 +529,7 @@ def dummy_diffprivlib_query_handler( - query_response (pd.DataFrame): a DataFrame containing the query response. """ - from app import app # pylint: disable=C0415 + app = request.app dataset_name = query_json.dataset_name if not app.state.admin_database.has_user_access_to_dataset( @@ -536,7 +538,7 @@ def dummy_diffprivlib_query_handler( raise UnauthorizedAccessException( f"{user_name} does not have access to {dataset_name}.", ) - + ds_private_dataset = get_dummy_dataset_for_query( app.state.admin_database, query_json ) @@ -561,6 +563,7 @@ def dummy_diffprivlib_query_handler( tags=["USER_QUERY"], ) def estimate_diffprivlib_cost( + request: Request, query_json: DiffPrivLibInp = Body(example_diffprivlib), user_name: str = Header(None), ): @@ -592,8 +595,8 @@ def estimate_diffprivlib_cost( - epsilon_cost (float): The estimated epsilon cost. - delta_cost (float): The estimated delta cost. """ - from app import app # pylint: disable=C0415 - + app = request.app + dataset_name = query_json.dataset_name if not app.state.admin_database.has_user_access_to_dataset( user_name, dataset_name diff --git a/server/lomas_server/tests/test_api_diffprivlib.py b/server/lomas_server/tests/test_api_diffprivlib.py index 079a4890..94db1846 100644 --- a/server/lomas_server/tests/test_api_diffprivlib.py +++ b/server/lomas_server/tests/test_api_diffprivlib.py @@ -324,7 +324,9 @@ def test_dummy_diffprivlib_query(self) -> None: with TestClient(app) as client: # Expect to work response = client.post( - "/dummy_diffprivlib_query", json=example_dummy_diffprivlib + "/dummy_diffprivlib_query", + json=example_dummy_diffprivlib, + headers=self.headers, ) assert response.status_code == status.HTTP_200_OK @@ -332,15 +334,45 @@ def test_dummy_diffprivlib_query(self) -> None: assert response_dict["query_response"]["score"] > 0 assert response_dict["query_response"]["model"] + # Expect to fail: user does have access to dataset + body = dict(example_dummy_diffprivlib) + body["dataset_name"] = "IRIS" + response = client.post( + "/dummy_diffprivlib_query", + json=body, + headers=self.headers, + ) + assert response.status_code == status.HTTP_403_FORBIDDEN + assert response.json() == { + "UnauthorizedAccessException": "" + + f"{self.user_name} does not have access to IRIS." + } + def test_diffprivlib_cost(self) -> None: """test_diffprivlib_cost""" with TestClient(app) as client: # Expect to work response = client.post( - "/estimate_diffprivlib_cost", json=example_diffprivlib + "/estimate_diffprivlib_cost", + json=example_diffprivlib, + headers=self.headers, ) assert response.status_code == status.HTTP_200_OK response_dict = json.loads(response.content.decode("utf8")) assert response_dict["epsilon_cost"] == 1.5 assert response_dict["delta_cost"] == 0 + + # Expect to fail: user does have access to dataset + body = dict(example_diffprivlib) + body["dataset_name"] = "IRIS" + response = client.post( + "/estimate_diffprivlib_cost", + json=body, + headers=self.headers, + ) + assert response.status_code == status.HTTP_403_FORBIDDEN + assert response.json() == { + "UnauthorizedAccessException": "" + + f"{self.user_name} does not have access to IRIS." + }