From a5b71361ad36ef51759711e7eba6dcec07a02e30 Mon Sep 17 00:00:00 2001 From: TheNoxium Date: Wed, 3 Dec 2025 19:29:59 +0530 Subject: [PATCH] fix: ps node models --- api/api/endpoints/ps_node.py | 256 +++++++++---------- api/api/schemas/process/ps_node.py | 16 +- api/api/services/endpoints/process_schema.py | 6 +- api/api/services/endpoints/ps_node.py | 24 +- 4 files changed, 153 insertions(+), 149 deletions(-) diff --git a/api/api/endpoints/ps_node.py b/api/api/endpoints/ps_node.py index 4eba806..63bc2c9 100644 --- a/api/api/endpoints/ps_node.py +++ b/api/api/endpoints/ps_node.py @@ -27,135 +27,6 @@ api_router = APIRouter( ) -@api_router.delete("", dependencies=[Depends(bearer_schema)], status_code=status.HTTP_200_OK) -async def delete_ps_node_endpoint( - ps_node_delete_data: Ps_NodeDeleteRequest, - connection: AsyncConnection = Depends(get_connection_dep), - current_user=Depends(get_current_user), -): - process_schema = await get_process_schema_by_id(connection, ps_node_delete_data.schema_id) - if process_schema is None: - raise create_operation_error( - message="Process schema not found", - status_code=status.HTTP_404_NOT_FOUND, - details={"schema_id": ps_node_delete_data.schema_id}, - ) - - validator = UserRoleValidator(connection) - try: - await validator.validate_ownership(current_user, process_schema.creator_id) - except Exception as e: - raise create_access_error( - message="Access denied", - status_code=status.HTTP_403_FORBIDDEN, - details={"user_id": current_user, "schema_creator_id": process_schema.creator_id, "reason": str(e)}, - ) - - ps_node = await get_ps_node_by_id(connection, ps_node_delete_data.node_id) - if ps_node is None: - raise create_operation_error( - message="PS node not found", - status_code=status.HTTP_404_NOT_FOUND, - details={"node_id": ps_node_delete_data.node_id}, - ) - - next_ps_node = await get_ps_node_by_id(connection, ps_node_delete_data.next_node_id) - if next_ps_node is None: - raise create_operation_error( - message="Next PS node not found", - status_code=status.HTTP_400_BAD_REQUEST, - details={"next_node_id": ps_node_delete_data.next_node_id}, - ) - - service = PsNodeService(connection) - try: - result = await service.delete(ps_node_delete_data.next_node_id) - except Exception as e: - raise create_server_error( - message="Failed to delete nodes", - status_code=500, - details={"error": str(e), "next_node_id": ps_node_delete_data.next_node_id}, - ) - - return result - - -@api_router.post("", dependencies=[Depends(bearer_schema)], response_model=Ps_NodeFrontResponse) -async def create_ps_node_endpoint( - ps_node: Ps_NodeRequest, - connection: AsyncConnection = Depends(get_connection_dep), - current_user=Depends(get_current_user), -): - user_validation = await get_user_by_login(connection, current_user) - - process_schema = await get_process_schema_by_id(connection, ps_node.data["ps_id"]) - if process_schema is None: - raise create_operation_error( - message="Process schema not found", - status_code=status.HTTP_404_NOT_FOUND, - details={"schema_id": ps_node.data["ps_id"]}, - ) - - validator = UserRoleValidator(connection) - try: - await validator.validate_ownership(current_user, process_schema.creator_id) - except Exception as e: - raise create_access_error( - message="Access denied", - status_code=status.HTTP_403_FORBIDDEN, - details={"user_id": current_user, "schema_creator_id": process_schema.creator_id, "reason": str(e)}, - ) - - registery = VorkNodeRegistry() - - vork_node = registery.get(ps_node.data["node_type"]) - - if vork_node is None: - raise create_operation_error( - message="Node type not found", - status_code=status.HTTP_404_NOT_FOUND, - details={"node_type": ps_node.data["node_type"]}, - ) - - try: - node_instance = vork_node(data=ps_node.data, links=ps_node.links) - node_instance_validated = node_instance.validate() - except Exception as e: - raise create_validation_error( - message="Node validation failed", - status_code=status.HTTP_400_BAD_REQUEST, - details={"error": str(e)}, - ) - - parent_id = node_instance_validated.parent_id - target_ps_id = ps_node.data["ps_id"] - - parent_node = await get_ps_node_by_id(connection, parent_id) - if parent_node is None: - raise create_operation_error( - message="Parent PS node not found", - status_code=status.HTTP_404_NOT_FOUND, - details={"parent_id": parent_id}, - ) - if parent_node.ps_id != target_ps_id: - raise create_validation_error( - message="Parent PS node belongs to another process schema", - status_code=status.HTTP_400_BAD_REQUEST, - details={"parent_id": parent_id, "expected_ps_id": target_ps_id, "actual_ps_id": parent_node.ps_id}, - ) - - service = PsNodeService(connection) - try: - ps_node_front_response = await service.create(ps_node.data, ps_node.links, user_validation.id) - except Exception as e: - raise create_server_error( - message="Failed to create node", - status_code=500, - details={"error": str(e)}, - ) - - return ps_node_front_response - @api_router.get("/available", dependencies=[Depends(bearer_schema)], response_model=AllAvailableNodesResponse) async def get_all_available_nodes_endpoint( @@ -184,12 +55,12 @@ async def get_ps_node_endpoint( details={"node_id": node_id}, ) - process_schema = await get_process_schema_by_id(connection, ps_node_response.node["ps_id"]) + process_schema = await get_process_schema_by_id(connection, ps_node_response.node.ps_id) if process_schema is None: raise create_operation_error( message="Process schema not found", status_code=status.HTTP_404_NOT_FOUND, - details={"schema_id": ps_node_response.node["ps_id"]}, + details={"schema_id": ps_node_response.node.ps_id}, ) validator = UserRoleValidator(connection) @@ -204,6 +75,75 @@ async def get_ps_node_endpoint( return ps_node_response +@api_router.post("", dependencies=[Depends(bearer_schema)], response_model=Ps_NodeFrontResponse) +async def create_ps_node_endpoint( + ps_node: Ps_NodeRequest, + connection: AsyncConnection = Depends(get_connection_dep), + current_user=Depends(get_current_user), +): + user_validation = await get_user_by_login(connection, current_user) + + process_schema = await get_process_schema_by_id(connection, ps_node.data.ps_id) + if process_schema is None: + raise create_operation_error( + message="Process schema not found", + status_code=status.HTTP_404_NOT_FOUND, + details={"schema_id": ps_node.data.ps_id}, + ) + + validator = UserRoleValidator(connection) + try: + await validator.validate_ownership(current_user, process_schema.creator_id) + except Exception as e: + raise create_access_error( + message="Access denied", + status_code=status.HTTP_403_FORBIDDEN, + details={"user_id": current_user, "schema_creator_id": process_schema.creator_id, "reason": str(e)}, + ) + + registery = VorkNodeRegistry() + + vork_node = registery.get(ps_node.data.node_type.value) + + if vork_node is None: + raise create_operation_error( + message="Node type not found", + status_code=status.HTTP_404_NOT_FOUND, + details={"node_type": ps_node.data.node_type}, + ) + + try: + # Преобразуем объекты Pydantic в словари для vork_node + node_instance = vork_node(data=ps_node.data.model_dump(), links=ps_node.links.model_dump()) + node_instance_validated = node_instance.validate() + except Exception as e: + raise create_validation_error( + message="Node validation failed", + status_code=status.HTTP_400_BAD_REQUEST, + details={"error": str(e)}, + ) + + parent_id = node_instance_validated.parent_id + target_ps_id = ps_node.data.ps_id + + parent_node = await get_ps_node_by_id(connection, parent_id) + if parent_node is None: + raise create_operation_error( + message="Parent PS node not found", + status_code=status.HTTP_404_NOT_FOUND, + details={"parent_id": parent_id}, + ) + if parent_node.ps_id != target_ps_id: + raise create_validation_error( + message="Parent PS node belongs to another process schema", + status_code=status.HTTP_400_BAD_REQUEST, + details={"parent_id": parent_id, "expected_ps_id": target_ps_id, "actual_ps_id": parent_node.ps_id}, + ) + + service = PsNodeService(connection) + ps_node_response = await service.create(ps_node.data.model_dump(), ps_node.links.model_dump(), user_validation.id) + + return ps_node_response @api_router.put("", dependencies=[Depends(bearer_schema)], response_model=Ps_NodeFrontResponse) async def update_ps_node_endpoint( @@ -292,3 +232,57 @@ async def update_ps_node_endpoint( ) return updated_ps_node + + + +@api_router.delete("", dependencies=[Depends(bearer_schema)], status_code=status.HTTP_200_OK) +async def delete_ps_node_endpoint( + ps_node_delete_data: Ps_NodeDeleteRequest, + connection: AsyncConnection = Depends(get_connection_dep), + current_user=Depends(get_current_user), +): + process_schema = await get_process_schema_by_id(connection, ps_node_delete_data.schema_id) + if process_schema is None: + raise create_operation_error( + message="Process schema not found", + status_code=status.HTTP_404_NOT_FOUND, + details={"schema_id": ps_node_delete_data.schema_id}, + ) + + validator = UserRoleValidator(connection) + try: + await validator.validate_ownership(current_user, process_schema.creator_id) + except Exception as e: + raise create_access_error( + message="Access denied", + status_code=status.HTTP_403_FORBIDDEN, + details={"user_id": current_user, "schema_creator_id": process_schema.creator_id, "reason": str(e)}, + ) + + ps_node = await get_ps_node_by_id(connection, ps_node_delete_data.node_id) + if ps_node is None: + raise create_operation_error( + message="PS node not found", + status_code=status.HTTP_404_NOT_FOUND, + details={"node_id": ps_node_delete_data.node_id}, + ) + + next_ps_node = await get_ps_node_by_id(connection, ps_node_delete_data.next_node_id) + if next_ps_node is None: + raise create_operation_error( + message="Next PS node not found", + status_code=status.HTTP_400_BAD_REQUEST, + details={"next_node_id": ps_node_delete_data.next_node_id}, + ) + + service = PsNodeService(connection) + try: + result = await service.delete(ps_node_delete_data.next_node_id) + except Exception as e: + raise create_server_error( + message="Failed to delete nodes", + status_code=500, + details={"error": str(e), "next_node_id": ps_node_delete_data.next_node_id}, + ) + + return result diff --git a/api/api/schemas/process/ps_node.py b/api/api/schemas/process/ps_node.py index b8f1264..cf51445 100644 --- a/api/api/schemas/process/ps_node.py +++ b/api/api/schemas/process/ps_node.py @@ -4,6 +4,7 @@ from typing import Any from orm.tables.process import NodeStatus, NodeType from api.schemas.base import Base +from api.schemas.process.node_link import NodeLink class Ps_NodeDeleteRequest(Base): @@ -12,10 +13,17 @@ class Ps_NodeDeleteRequest(Base): port: str next_node_id: int +class Ps_NodeRequestData(Base): + ps_id: int + node_type: NodeType + +class Ps_NodeRequestLinks(Base): + parent_port_number: int + parent_id: int class Ps_NodeRequest(Base): - data: dict[str, Any] - links: dict[str, Any] + data: Ps_NodeRequestData + links: Ps_NodeRequestLinks class Ps_Node(Base): @@ -35,8 +43,8 @@ class Ps_NodeUpdate(Base): class Ps_NodeFrontResponse(Base): - node: dict[str, Any] | None = None - link: list[dict[str, Any]] | None = None + node: Ps_Node + link: list[NodeLink] | None = None class AllAvailableNodesResponse(Base): diff --git a/api/api/services/endpoints/process_schema.py b/api/api/services/endpoints/process_schema.py index 7e031b0..367c500 100644 --- a/api/api/services/endpoints/process_schema.py +++ b/api/api/services/endpoints/process_schema.py @@ -53,11 +53,11 @@ class ProcessSchemaService: nodes_response = [] for node in nodes: node_links = links_by_node_id.get(node.id, []) - links_list = [{"link": link.model_dump()} for link in node_links] + link = node_links if node_links else None ps_node_front_response = Ps_NodeFrontResponse( node=node.model_dump(), - link=links_list, + link=link, ) nodes_response.append(ps_node_front_response) @@ -107,7 +107,7 @@ class ProcessSchemaService: ps_node_front_response = Ps_NodeFrontResponse( node=db_start_schema.model_dump(), - link=[], + link=None, ) response_data = { "process_schema": process_schema_new.model_dump(), diff --git a/api/api/services/endpoints/ps_node.py b/api/api/services/endpoints/ps_node.py index 41e02e3..b29ed20 100644 --- a/api/api/services/endpoints/ps_node.py +++ b/api/api/services/endpoints/ps_node.py @@ -42,7 +42,10 @@ class PsNodeService: Создаёт новую ноду с линком и обновляет настройки схемы процесса. """ registery = VorkNodeRegistry() - vork_node = registery.get(ps_node_data["node_type"]) + + node_type = ps_node_data.get("node_type") + vork_node = registery.get(node_type.value) + node_descriptor = vork_node.form() node_instance = vork_node(data=ps_node_data, links=links) @@ -64,8 +67,8 @@ class PsNodeService: db_node_link = await create_node_link_schema(self.connection, validated_link, creator_id) ps_node_front_response = Ps_NodeFrontResponse( - node=db_ps_node.model_dump(), - link=[{"link": db_node_link.model_dump()}], + node=db_ps_node, + link=[db_node_link] if db_node_link else None, ) return ps_node_front_response @@ -80,29 +83,28 @@ class PsNodeService: node_links = await get_all_node_links_by_next_node_ids(self.connection, [node_id]) - links_list = [{"link": link.model_dump()} for link in node_links] - return Ps_NodeFrontResponse( - node=ps_node.model_dump(), - link=links_list, + node=ps_node, + link=node_links if node_links else None, ) async def update(self, node_id: int, update_data: dict[str, Any], ps_node: Ps_Node) -> Ps_NodeFrontResponse: """ Обновляет данные PS ноды (settings). + Принимает уже полученную ноду, чтобы избежать лишних запросов к БД. """ - await update_ps_node_by_id(self.connection, {"settings": update_data}, ps_node) node_links = await get_all_node_links_by_next_node_ids(self.connection, [node_id]) - links_list = [{"link": link.model_dump()} for link in node_links] + # Создаем обновленный объект Ps_Node с новыми settings updated_node_dict = ps_node.model_dump() updated_node_dict["settings"] = update_data + updated_ps_node = Ps_Node.model_validate(updated_node_dict) return Ps_NodeFrontResponse( - node=updated_node_dict, - link=links_list, + node=updated_ps_node, + link=node_links if node_links else None, ) def check_constraint(self, form_descriptor: dict[str, Any], settings_data: dict[str, Any]) -> bool: