backend: validate flow_id on api (#1927)
This commit is contained in:
parent
73cee13165
commit
dd344ce6c6
3 changed files with 27 additions and 15 deletions
|
|
@ -53,7 +53,7 @@ async def try_running_celery_task(vertex, user_id):
|
||||||
|
|
||||||
@router.post("/build/{flow_id}/vertices", response_model=VerticesOrderResponse)
|
@router.post("/build/{flow_id}/vertices", response_model=VerticesOrderResponse)
|
||||||
async def retrieve_vertices_order(
|
async def retrieve_vertices_order(
|
||||||
flow_id: str,
|
flow_id: uuid.UUID,
|
||||||
data: Optional[Annotated[Optional[FlowDataRequest], Body(embed=True)]] = None,
|
data: Optional[Annotated[Optional[FlowDataRequest], Body(embed=True)]] = None,
|
||||||
stop_component_id: Optional[str] = None,
|
stop_component_id: Optional[str] = None,
|
||||||
start_component_id: Optional[str] = None,
|
start_component_id: Optional[str] = None,
|
||||||
|
|
@ -78,6 +78,7 @@ async def retrieve_vertices_order(
|
||||||
HTTPException: If there is an error checking the build status.
|
HTTPException: If there is an error checking the build status.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
flow_id = str(flow_id)
|
||||||
# First, we need to check if the flow_id is in the cache
|
# First, we need to check if the flow_id is in the cache
|
||||||
if not data:
|
if not data:
|
||||||
graph = await build_and_cache_graph_from_db(flow_id=flow_id, session=session, chat_service=chat_service)
|
graph = await build_and_cache_graph_from_db(flow_id=flow_id, session=session, chat_service=chat_service)
|
||||||
|
|
@ -119,7 +120,7 @@ async def retrieve_vertices_order(
|
||||||
|
|
||||||
@router.post("/build/{flow_id}/vertices/{vertex_id}")
|
@router.post("/build/{flow_id}/vertices/{vertex_id}")
|
||||||
async def build_vertex(
|
async def build_vertex(
|
||||||
flow_id: str,
|
flow_id: uuid.UUID,
|
||||||
vertex_id: str,
|
vertex_id: str,
|
||||||
background_tasks: BackgroundTasks,
|
background_tasks: BackgroundTasks,
|
||||||
inputs: Annotated[Optional[InputValueRequest], Body(embed=True)] = None,
|
inputs: Annotated[Optional[InputValueRequest], Body(embed=True)] = None,
|
||||||
|
|
@ -143,8 +144,8 @@ async def build_vertex(
|
||||||
HTTPException: If there is an error building the vertex.
|
HTTPException: If there is an error building the vertex.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
flow_id = str(flow_id)
|
||||||
|
|
||||||
start_time = time.perf_counter()
|
|
||||||
next_runnable_vertices = []
|
next_runnable_vertices = []
|
||||||
top_level_vertices = []
|
top_level_vertices = []
|
||||||
try:
|
try:
|
||||||
|
|
@ -158,8 +159,7 @@ async def build_vertex(
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
graph = cache.get("result")
|
graph = cache.get("result")
|
||||||
result_data_response = ResultDataResponse(results={})
|
ResultDataResponse(results={})
|
||||||
duration = ""
|
|
||||||
vertex = graph.get_vertex(vertex_id)
|
vertex = graph.get_vertex(vertex_id)
|
||||||
try:
|
try:
|
||||||
lock = chat_service._cache_locks[flow_id]
|
lock = chat_service._cache_locks[flow_id]
|
||||||
|
|
@ -240,7 +240,7 @@ async def build_vertex(
|
||||||
|
|
||||||
@router.get("/build/{flow_id}/{vertex_id}/stream", response_class=StreamingResponse)
|
@router.get("/build/{flow_id}/{vertex_id}/stream", response_class=StreamingResponse)
|
||||||
async def build_vertex_stream(
|
async def build_vertex_stream(
|
||||||
flow_id: str,
|
flow_id: uuid.UUID,
|
||||||
vertex_id: str,
|
vertex_id: str,
|
||||||
session_id: Optional[str] = None,
|
session_id: Optional[str] = None,
|
||||||
chat_service: "ChatService" = Depends(get_chat_service),
|
chat_service: "ChatService" = Depends(get_chat_service),
|
||||||
|
|
@ -272,6 +272,7 @@ async def build_vertex_stream(
|
||||||
HTTPException: If an error occurs while building the vertex.
|
HTTPException: If an error occurs while building the vertex.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
flow_id = str(flow_id)
|
||||||
|
|
||||||
async def stream_vertex():
|
async def stream_vertex():
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
from typing import Annotated, List, Optional, Union
|
from typing import Annotated, List, Optional, Union
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from fastapi import APIRouter, Body, Depends, HTTPException, UploadFile, status
|
from fastapi import APIRouter, Body, Depends, HTTPException, UploadFile, status
|
||||||
|
|
@ -54,7 +55,7 @@ def get_all(
|
||||||
@router.post("/run/{flow_id}", response_model=RunResponse, response_model_exclude_none=True)
|
@router.post("/run/{flow_id}", response_model=RunResponse, response_model_exclude_none=True)
|
||||||
async def simplified_run_flow(
|
async def simplified_run_flow(
|
||||||
db: Annotated[Session, Depends(get_session)],
|
db: Annotated[Session, Depends(get_session)],
|
||||||
flow_id: str,
|
flow_id: UUID,
|
||||||
input_request: SimplifiedAPIRequest = SimplifiedAPIRequest(),
|
input_request: SimplifiedAPIRequest = SimplifiedAPIRequest(),
|
||||||
stream: bool = False,
|
stream: bool = False,
|
||||||
api_key_user: User = Depends(api_key_security),
|
api_key_user: User = Depends(api_key_security),
|
||||||
|
|
@ -111,6 +112,7 @@ async def simplified_run_flow(
|
||||||
session_id = input_request.session_id
|
session_id = input_request.session_id
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
flow_id = str(flow_id)
|
||||||
task_result: List[RunOutputs] = []
|
task_result: List[RunOutputs] = []
|
||||||
artifacts = {}
|
artifacts = {}
|
||||||
if input_request.session_id:
|
if input_request.session_id:
|
||||||
|
|
@ -187,7 +189,7 @@ async def simplified_run_flow(
|
||||||
@router.post("/run/advanced/{flow_id}", response_model=RunResponse, response_model_exclude_none=True)
|
@router.post("/run/advanced/{flow_id}", response_model=RunResponse, response_model_exclude_none=True)
|
||||||
async def experimental_run_flow(
|
async def experimental_run_flow(
|
||||||
session: Annotated[Session, Depends(get_session)],
|
session: Annotated[Session, Depends(get_session)],
|
||||||
flow_id: str,
|
flow_id: UUID,
|
||||||
inputs: Optional[List[InputValueRequest]] = [InputValueRequest(components=[], input_value="")],
|
inputs: Optional[List[InputValueRequest]] = [InputValueRequest(components=[], input_value="")],
|
||||||
outputs: Optional[List[str]] = [],
|
outputs: Optional[List[str]] = [],
|
||||||
tweaks: Annotated[Optional[Tweaks], Body(embed=True)] = None, # noqa: F821
|
tweaks: Annotated[Optional[Tweaks], Body(embed=True)] = None, # noqa: F821
|
||||||
|
|
@ -235,6 +237,7 @@ async def experimental_run_flow(
|
||||||
This endpoint facilitates complex flow executions with customized inputs, outputs, and configurations, catering to diverse application requirements.
|
This endpoint facilitates complex flow executions with customized inputs, outputs, and configurations, catering to diverse application requirements.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
flow_id = str(flow_id)
|
||||||
if outputs is None:
|
if outputs is None:
|
||||||
outputs = []
|
outputs = []
|
||||||
|
|
||||||
|
|
@ -357,9 +360,10 @@ async def get_task_status(task_id: str):
|
||||||
)
|
)
|
||||||
async def create_upload_file(
|
async def create_upload_file(
|
||||||
file: UploadFile,
|
file: UploadFile,
|
||||||
flow_id: str,
|
flow_id: UUID,
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
|
flow_id = str(flow_id)
|
||||||
file_path = save_uploaded_file(file, folder_name=flow_id)
|
file_path = save_uploaded_file(file, folder_name=flow_id)
|
||||||
|
|
||||||
return UploadFileResponse(
|
return UploadFileResponse(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import hashlib
|
import hashlib
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, HTTPException, UploadFile
|
from fastapi import APIRouter, Depends, HTTPException, UploadFile
|
||||||
from fastapi.responses import StreamingResponse
|
from fastapi.responses import StreamingResponse
|
||||||
|
|
@ -20,10 +21,11 @@ router = APIRouter(tags=["Files"], prefix="/files")
|
||||||
# then finds it in the database and returns it while
|
# then finds it in the database and returns it while
|
||||||
# using the current user as the owner
|
# using the current user as the owner
|
||||||
def get_flow_id(
|
def get_flow_id(
|
||||||
flow_id: str,
|
flow_id: UUID,
|
||||||
current_user=Depends(get_current_active_user),
|
current_user=Depends(get_current_active_user),
|
||||||
session=Depends(get_session),
|
session=Depends(get_session),
|
||||||
):
|
):
|
||||||
|
flow_id = str(flow_id)
|
||||||
# AttributeError: 'SelectOfScalar' object has no attribute 'first'
|
# AttributeError: 'SelectOfScalar' object has no attribute 'first'
|
||||||
flow = session.get(Flow, flow_id)
|
flow = session.get(Flow, flow_id)
|
||||||
if not flow:
|
if not flow:
|
||||||
|
|
@ -36,10 +38,11 @@ def get_flow_id(
|
||||||
@router.post("/upload/{flow_id}", status_code=HTTPStatus.CREATED)
|
@router.post("/upload/{flow_id}", status_code=HTTPStatus.CREATED)
|
||||||
async def upload_file(
|
async def upload_file(
|
||||||
file: UploadFile,
|
file: UploadFile,
|
||||||
flow_id: str = Depends(get_flow_id),
|
flow_id: UUID = Depends(get_flow_id),
|
||||||
storage_service: StorageService = Depends(get_storage_service),
|
storage_service: StorageService = Depends(get_storage_service),
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
|
flow_id = str(flow_id)
|
||||||
file_content = await file.read()
|
file_content = await file.read()
|
||||||
file_name = file.filename or hashlib.sha256(file_content).hexdigest()
|
file_name = file.filename or hashlib.sha256(file_content).hexdigest()
|
||||||
folder = flow_id
|
folder = flow_id
|
||||||
|
|
@ -50,8 +53,9 @@ async def upload_file(
|
||||||
|
|
||||||
|
|
||||||
@router.get("/download/{flow_id}/{file_name}")
|
@router.get("/download/{flow_id}/{file_name}")
|
||||||
async def download_file(file_name: str, flow_id: str, storage_service: StorageService = Depends(get_storage_service)):
|
async def download_file(file_name: str, flow_id: UUID, storage_service: StorageService = Depends(get_storage_service)):
|
||||||
try:
|
try:
|
||||||
|
flow_id = str(flow_id)
|
||||||
extension = file_name.split(".")[-1]
|
extension = file_name.split(".")[-1]
|
||||||
|
|
||||||
if not extension:
|
if not extension:
|
||||||
|
|
@ -74,9 +78,10 @@ async def download_file(file_name: str, flow_id: str, storage_service: StorageSe
|
||||||
|
|
||||||
|
|
||||||
@router.get("/images/{flow_id}/{file_name}")
|
@router.get("/images/{flow_id}/{file_name}")
|
||||||
async def download_image(file_name: str, flow_id: str, storage_service: StorageService = Depends(get_storage_service)):
|
async def download_image(file_name: str, flow_id: UUID, storage_service: StorageService = Depends(get_storage_service)):
|
||||||
try:
|
try:
|
||||||
extension = file_name.split(".")[-1]
|
extension = file_name.split(".")[-1]
|
||||||
|
flow_id = str(flow_id)
|
||||||
|
|
||||||
if not extension:
|
if not extension:
|
||||||
raise HTTPException(status_code=500, detail=f"Extension not found for file {file_name}")
|
raise HTTPException(status_code=500, detail=f"Extension not found for file {file_name}")
|
||||||
|
|
@ -96,9 +101,10 @@ async def download_image(file_name: str, flow_id: str, storage_service: StorageS
|
||||||
|
|
||||||
@router.get("/list/{flow_id}")
|
@router.get("/list/{flow_id}")
|
||||||
async def list_files(
|
async def list_files(
|
||||||
flow_id: str = Depends(get_flow_id), storage_service: StorageService = Depends(get_storage_service)
|
flow_id: UUID = Depends(get_flow_id), storage_service: StorageService = Depends(get_storage_service)
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
|
flow_id = str(flow_id)
|
||||||
files = await storage_service.list_files(flow_id=flow_id)
|
files = await storage_service.list_files(flow_id=flow_id)
|
||||||
return {"files": files}
|
return {"files": files}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
@ -107,9 +113,10 @@ async def list_files(
|
||||||
|
|
||||||
@router.delete("/delete/{flow_id}/{file_name}")
|
@router.delete("/delete/{flow_id}/{file_name}")
|
||||||
async def delete_file(
|
async def delete_file(
|
||||||
file_name: str, flow_id: str = Depends(get_flow_id), storage_service: StorageService = Depends(get_storage_service)
|
file_name: str, flow_id: UUID = Depends(get_flow_id), storage_service: StorageService = Depends(get_storage_service)
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
|
flow_id = str(flow_id)
|
||||||
await storage_service.delete_file(flow_id=flow_id, file_name=file_name)
|
await storage_service.delete_file(flow_id=flow_id, file_name=file_name)
|
||||||
return {"message": f"File {file_name} deleted successfully"}
|
return {"message": f"File {file_name} deleted successfully"}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue