diff --git a/api/api/endpoints/ps_node.py b/api/api/endpoints/ps_node.py index bfe0944..1eb17b3 100644 --- a/api/api/endpoints/ps_node.py +++ b/api/api/endpoints/ps_node.py @@ -121,14 +121,33 @@ async def create_ps_node_endpoint( process_schema = await get_process_schema_by_id(connection, ps_node.data["ps_id"]) if process_schema is None: - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Process schema not found") + raise create_operation_error( + message="Process schema not found", + status_code=status.HTTP_404_NOT_FOUND, + details={"schema_id": ps_node.data["ps_id"]}, + ) + + try: + await db_user_role_validation_for_list_events_and_process_schema_by_list_event_id( + connection, 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 HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Node not found") + raise create_operation_error( + message="Node type not found", + status_code=status.HTTP_404_NOT_FOUND, + details={"node_type": ps_node.data["node_type"]}, + ) node_descriptor = vork_node.form() try: @@ -137,43 +156,93 @@ async def create_ps_node_endpoint( node_instance_validated = node_instance.validate() except Exception as e: - raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) + raise create_validation_error( + message="Node validation failed", + status_code=status.HTTP_400_BAD_REQUEST, + details={"error": str(e)}, + ) - db_ps_node = await create_ps_node_schema(connection, node_instance_validated, user_validation.id) - link_name = await get_last_link_name_by_node_id(connection, db_ps_node.ps_id) + # Проверка: parent_id принадлежит тому же ps_id + parent_id = node_instance_validated.parent_id + target_ps_id = ps_node.data["ps_id"] - link_data = VorkNodeLinkData( - parent_port_number=node_instance_validated.parent_port_number, - to_id=db_ps_node.id, - from_id=node_instance_validated.parent_id, - last_link_name=link_name, - ) + 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}, + ) - link = VorkNodeLink(data=link_data.model_dump()) + # Проверка: у родительской ноды есть указанный порт + parent_port_number = node_instance_validated.parent_port_number - validated_link = link.validate() + # Извлекаем номера портов из settings родительской ноды + parent_settings = parent_node.settings or {} + available_port_numbers = [] - db_node_link = await create_node_link_schema(connection, validated_link, user_validation.id) + # Ищем все ключи, содержащие "port" в названии + for key, value in parent_settings.items(): + if "port" in key.lower() and isinstance(value, int): + available_port_numbers.append(value) - links_settings = ProcessSchemaSettingsNodeLink( - id=db_node_link.id, - link_name=db_node_link.link_name, - parent_port_number=db_node_link.link_point_id, - from_id=db_node_link.node_id, - to_id=db_node_link.next_node_id, - ) + # Проверяем, что указанный порт существует в settings + if parent_port_number not in available_port_numbers: + raise create_validation_error( + message="Parent port number is invalid", + status_code=status.HTTP_400_BAD_REQUEST, + details={"parent_id": parent_id, "parent_settings": parent_settings}, + ) - node_settings = ProcessSchemaSettingsNode( - id=db_ps_node.id, - node_type=db_ps_node.node_type, - data=node_instance_validated.data.model_dump(), - from_node=None, - links=[{"links": links_settings.model_dump()}], - ) + try: + db_ps_node = await create_ps_node_schema(connection, node_instance_validated, user_validation.id) + link_name = await get_last_link_name_by_node_id(connection, db_ps_node.ps_id) - settings_dict = {"node": node_settings.model_dump(mode="json")} + link_data = VorkNodeLinkData( + parent_port_number=node_instance_validated.parent_port_number, + to_id=db_ps_node.id, + from_id=node_instance_validated.parent_id, + last_link_name=link_name, + ) - await update_process_schema_settings_by_id(connection, db_ps_node.ps_id, settings_dict) + link = VorkNodeLink(data=link_data.model_dump()) + + validated_link = link.validate() + + db_node_link = await create_node_link_schema(connection, validated_link, user_validation.id) + + links_settings = ProcessSchemaSettingsNodeLink( + id=db_node_link.id, + link_name=db_node_link.link_name, + parent_port_number=db_node_link.link_point_id, + from_id=db_node_link.node_id, + to_id=db_node_link.next_node_id, + ) + + node_settings = ProcessSchemaSettingsNode( + id=db_ps_node.id, + node_type=db_ps_node.node_type, + data=node_instance_validated.data.model_dump(), + from_node=None, + links=[{"links": links_settings.model_dump()}], + ) + + settings_dict = {"node": node_settings.model_dump(mode="json")} + + await update_process_schema_settings_by_id(connection, db_ps_node.ps_id, settings_dict) + + except Exception as e: + raise create_server_error( + message="Failed to create node", + status_code=500, + details={"error": str(e)}, + ) ps_node_front_response = Ps_NodeFrontResponse( description=node_descriptor.model_dump(),