687 lines
No EOL
26 KiB
Python
687 lines
No EOL
26 KiB
Python
"""
|
|
Workflow routes for the backend API.
|
|
Implements the endpoints for workflow management according to the state machine.
|
|
"""
|
|
|
|
import os
|
|
import json
|
|
import logging
|
|
from typing import List, Dict, Any, Optional
|
|
from fastapi import APIRouter, HTTPException, Depends, Body, Path, Query, Response, status
|
|
from datetime import datetime
|
|
|
|
# Import interfaces
|
|
from modules.interfaces.lucydomInterface import getInterface as getInterfaceLucydom
|
|
from modules.interfaces.msftInterface import getInterface as getInterfaceMsft
|
|
from modules.security.auth import getCurrentActiveUser
|
|
from modules.workflow.workflowManager import getWorkflowManager
|
|
|
|
# Import models
|
|
from modules.interfaces import lucydomModel as Models
|
|
|
|
# Configure logger
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# Create router for workflow endpoints
|
|
router = APIRouter(
|
|
prefix="/api/workflows",
|
|
tags=["Workflow"],
|
|
responses={404: {"description": "Not found"}}
|
|
)
|
|
|
|
# State 1: Workflow Initialization endpoint
|
|
@router.post("/start", response_model=Dict[str, Any])
|
|
async def startWorkflow(
|
|
workflowId: Optional[str] = Query(None, description="Optional ID of the workflow to continue"),
|
|
userInput: Models.UserInputRequest = Body(...),
|
|
currentUser: Dict[str, Any] = Depends(getCurrentActiveUser)
|
|
):
|
|
"""
|
|
Starts a new workflow or continues an existing one.
|
|
Corresponds to State 1 in the state machine documentation.
|
|
"""
|
|
try:
|
|
# Get interface with current user context
|
|
interfaceBase = getInterfaceLucydom(currentUser)
|
|
interfaceMsft = getInterfaceMsft(currentUser)
|
|
|
|
# Convert the user input to a dictionary
|
|
userInputDict = {
|
|
"prompt": userInput.prompt,
|
|
"listFileId": userInput.listFileId
|
|
}
|
|
|
|
# Get workflow manager with interface
|
|
workflowManager = await getWorkflowManager(interfaceBase, interfaceMsft)
|
|
|
|
# Start or continue workflow using the workflow manager
|
|
workflow = await workflowManager.workflowStart(userInputDict, workflowId)
|
|
logger.info("User Input received. Answer:", workflow)
|
|
|
|
return {
|
|
"id": workflow.get("id"),
|
|
"status": workflow.get("status", "running"),
|
|
"message": "Workflow initialized and processing started"
|
|
}
|
|
except Exception as e:
|
|
logger.error(f"Error starting workflow: {str(e)}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Error starting workflow: {str(e)}"
|
|
)
|
|
|
|
# State 8: Workflow Stopped endpoint
|
|
@router.post("/{workflowId}/stop", response_model=Dict[str, Any])
|
|
async def stopWorkflow(
|
|
workflowId: str = Path(..., description="ID of the workflow to stop"),
|
|
currentUser: Dict[str, Any] = Depends(getCurrentActiveUser)
|
|
):
|
|
"""Stops a running workflow."""
|
|
try:
|
|
# Get interface with current user context
|
|
interfaceBase = getInterfaceLucydom(currentUser)
|
|
interfaceMsft = getInterfaceMsft(currentUser)
|
|
|
|
# Verify workflow exists and belongs to user
|
|
workflow = interfaceBase.getWorkflow(workflowId)
|
|
if not workflow:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Workflow with ID {workflowId} not found"
|
|
)
|
|
|
|
if workflow.get("_userId") != currentUser["id"]:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="You don't have permission to stop this workflow"
|
|
)
|
|
|
|
# Stop the workflow
|
|
workflowManager = await getWorkflowManager(interfaceBase, interfaceMsft)
|
|
stoppedWorkflow = await workflowManager.workflowStop(workflowId)
|
|
|
|
return {
|
|
"id": workflowId,
|
|
"status": stoppedWorkflow.get("status", "stopped"),
|
|
"message": "Workflow has been stopped"
|
|
}
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error stopping workflow: {str(e)}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Error stopping workflow: {str(e)}"
|
|
)
|
|
|
|
# State 11: Workflow Reset/Deletion endpoint
|
|
@router.delete("/{workflowId}", response_model=Dict[str, Any])
|
|
async def deleteWorkflow(
|
|
workflowId: str = Path(..., description="ID of the workflow to delete"),
|
|
currentUser: Dict[str, Any] = Depends(getCurrentActiveUser)
|
|
):
|
|
"""Deletes a workflow and its associated data."""
|
|
try:
|
|
# Get interface with current user context
|
|
interfaceBase = getInterfaceLucydom(currentUser)
|
|
|
|
# Verify workflow exists
|
|
workflow = interfaceBase.getWorkflow(workflowId)
|
|
if not workflow:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Workflow with ID {workflowId} not found"
|
|
)
|
|
|
|
# Check if user has permission to delete
|
|
if workflow.get("_userId") != currentUser["id"]:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="You don't have permission to delete this workflow"
|
|
)
|
|
|
|
# Delete workflow
|
|
success = interfaceBase.deleteWorkflow(workflowId)
|
|
|
|
if not success:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="Failed to delete workflow"
|
|
)
|
|
|
|
return {
|
|
"id": workflowId,
|
|
"message": "Workflow and associated data deleted successfully"
|
|
}
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error deleting workflow: {str(e)}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Error deleting workflow: {str(e)}"
|
|
)
|
|
|
|
# API Endpoint for getting all workflows
|
|
@router.get("", response_model=List[Dict[str, Any]])
|
|
async def listWorkflows(
|
|
currentUser: Dict[str, Any] = Depends(getCurrentActiveUser)
|
|
):
|
|
"""List all workflows for the current user."""
|
|
try:
|
|
# Get interface with current user context
|
|
interfaceBase = getInterfaceLucydom(currentUser)
|
|
|
|
# Retrieve workflows for the user
|
|
workflows = interfaceBase.getWorkflowsByUser(currentUser["id"])
|
|
return workflows
|
|
except Exception as e:
|
|
logger.error(f"Error listing workflows: {str(e)}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Error listing workflows: {str(e)}"
|
|
)
|
|
|
|
# API Endpoint for workflow status
|
|
@router.get("/{workflowId}/status", response_model=Dict[str, Any])
|
|
async def getWorkflowStatus(
|
|
workflowId: str = Path(..., description="ID of the workflow"),
|
|
currentUser: Dict[str, Any] = Depends(getCurrentActiveUser)
|
|
):
|
|
"""Get the current status of a workflow."""
|
|
try:
|
|
# Get interface with current user context
|
|
interfaceBase = getInterfaceLucydom(currentUser)
|
|
|
|
# Retrieve workflow
|
|
workflow = interfaceBase.getWorkflow(workflowId)
|
|
if not workflow:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Workflow with ID {workflowId} not found"
|
|
)
|
|
|
|
# Create status response
|
|
statusInfo = {
|
|
"id": workflow.get("id"),
|
|
"name": workflow.get("name"),
|
|
"status": workflow.get("status"),
|
|
"startedAt": workflow.get("startedAt"),
|
|
"lastActivity": workflow.get("lastActivity"),
|
|
"currentRound": workflow.get("currentRound", 1),
|
|
"dataStats": workflow.get("dataStats", {})
|
|
}
|
|
|
|
return statusInfo
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error getting workflow status: {str(e)}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Error getting workflow status: {str(e)}"
|
|
)
|
|
|
|
# API Endpoint for workflow logs with selective data transfer
|
|
@router.get("/{workflowId}/logs", response_model=List[Dict[str, Any]])
|
|
async def getWorkflowLogs(
|
|
workflowId: str = Path(..., description="ID of the workflow"),
|
|
logId: Optional[str] = Query(None, description="Optional log ID to get only newer logs"),
|
|
currentUser: Dict[str, Any] = Depends(getCurrentActiveUser)
|
|
):
|
|
"""Get logs for a workflow with support for selective data transfer."""
|
|
try:
|
|
# Get interface with current user context
|
|
interfaceBase = getInterfaceLucydom(currentUser)
|
|
|
|
# Verify workflow exists
|
|
workflow = interfaceBase.getWorkflow(workflowId)
|
|
if not workflow:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Workflow with ID {workflowId} not found"
|
|
)
|
|
|
|
# Get all logs
|
|
allLogs = interfaceBase.getWorkflowLogs(workflowId)
|
|
|
|
# Apply selective data transfer if logId is provided
|
|
if logId:
|
|
# Find the index of the log with the given ID
|
|
logIndex = next((i for i, log in enumerate(allLogs) if log.get("id") == logId), -1)
|
|
if logIndex >= 0:
|
|
# Return only logs after the specified log
|
|
return allLogs[logIndex + 1:]
|
|
|
|
return allLogs
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error getting workflow logs: {str(e)}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Error getting workflow logs: {str(e)}"
|
|
)
|
|
|
|
# API Endpoint for workflow messages with selective data transfer
|
|
@router.get("/{workflowId}/messages", response_model=List[Dict[str, Any]])
|
|
async def getWorkflowMessages(
|
|
workflowId: str = Path(..., description="ID of the workflow"),
|
|
messageId: Optional[str] = Query(None, description="Optional message ID to get only newer messages"),
|
|
currentUser: Dict[str, Any] = Depends(getCurrentActiveUser)
|
|
):
|
|
"""Get messages for a workflow with support for selective data transfer."""
|
|
try:
|
|
# Get admin user for workflow operations
|
|
interfaceBase = getInterfaceLucydom(currentUser)
|
|
|
|
# Verify workflow exists
|
|
workflow = interfaceBase.getWorkflow(workflowId)
|
|
if not workflow:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Workflow with ID {workflowId} not found"
|
|
)
|
|
|
|
# Get all messages
|
|
allMessages = interfaceBase.getWorkflowMessages(workflowId)
|
|
|
|
# Apply selective data transfer if messageId is provided
|
|
if messageId:
|
|
# Find the index of the specified message based on messageIds array
|
|
messageIds = workflow.get("messageIds", [])
|
|
if messageId in messageIds:
|
|
messageIndex = messageIds.index(messageId)
|
|
# Return messages from this index onwards based on the messageIds order
|
|
filteredMessages = []
|
|
for msgId in messageIds[messageIndex:]:
|
|
message = next((msg for msg in allMessages if msg.get("id") == msgId), None)
|
|
if message:
|
|
filteredMessages.append(message)
|
|
return filteredMessages
|
|
|
|
# Sort messages by sequenceNo
|
|
allMessages.sort(key=lambda x: x.get("sequenceNo", 0))
|
|
return allMessages
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error getting workflow messages: {str(e)}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Error getting workflow messages: {str(e)}"
|
|
)
|
|
|
|
# Document Management Endpoints
|
|
|
|
@router.delete("/{workflowId}/messages/{messageId}", response_model=Dict[str, Any])
|
|
async def deleteWorkflowMessage(
|
|
workflowId: str = Path(..., description="ID of the workflow"),
|
|
messageId: str = Path(..., description="ID of the message to delete"),
|
|
currentUser: Dict[str, Any] = Depends(getCurrentActiveUser)
|
|
):
|
|
"""Delete a message from a workflow."""
|
|
try:
|
|
# Get admin user for workflow operations
|
|
interfaceBase = getInterfaceLucydom(currentUser)
|
|
|
|
# Verify workflow exists and belongs to user
|
|
workflow = interfaceBase.getWorkflow(workflowId)
|
|
if not workflow:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Workflow with ID {workflowId} not found"
|
|
)
|
|
|
|
# Delete the message
|
|
success = interfaceBase.deleteWorkflowMessage(workflowId, messageId)
|
|
|
|
if not success:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Message with ID {messageId} not found in workflow {workflowId}"
|
|
)
|
|
|
|
# Update workflow's messageIds
|
|
messageIds = workflow.get("messageIds", [])
|
|
if messageId in messageIds:
|
|
messageIds.remove(messageId)
|
|
interfaceBase.updateWorkflow(workflowId, {"messageIds": messageIds})
|
|
|
|
return {
|
|
"workflowId": workflowId,
|
|
"messageId": messageId,
|
|
"message": "Message deleted successfully"
|
|
}
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error deleting message: {str(e)}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Error deleting message: {str(e)}"
|
|
)
|
|
|
|
@router.delete("/{workflowId}/messages/{messageId}/files/{fileId}", response_model=Dict[str, Any])
|
|
async def deleteFileFromMessage(
|
|
workflowId: str = Path(..., description="ID of the workflow"),
|
|
messageId: str = Path(..., description="ID of the message"),
|
|
fileId: str = Path(..., description="ID of the file to delete"),
|
|
currentUser: Dict[str, Any] = Depends(getCurrentActiveUser)
|
|
):
|
|
"""Delete a file reference from a message in a workflow."""
|
|
try:
|
|
# Get admin user for workflow operations
|
|
interfaceBase = getInterfaceLucydom(currentUser)
|
|
|
|
# Verify workflow exists and belongs to user
|
|
workflow = interfaceBase.getWorkflow(workflowId)
|
|
if not workflow:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Workflow with ID {workflowId} not found"
|
|
)
|
|
|
|
# Delete file reference from message
|
|
success = interfaceBase.deleteFileFromMessage(workflowId, messageId, fileId)
|
|
|
|
if not success:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"File with ID {fileId} not found in message {messageId}"
|
|
)
|
|
|
|
return {
|
|
"workflowId": workflowId,
|
|
"messageId": messageId,
|
|
"fileId": fileId,
|
|
"message": "File reference deleted successfully"
|
|
}
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error deleting file reference: {str(e)}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Error deleting file reference: {str(e)}"
|
|
)
|
|
|
|
# File preview and download routes
|
|
|
|
@router.get("/files/{fileId}/preview", response_model=Dict[str, Any])
|
|
async def previewFile(
|
|
fileId: str = Path(..., description="ID of the file to preview"),
|
|
currentUser: Dict[str, Any] = Depends(getCurrentActiveUser)
|
|
):
|
|
"""Get file metadata and a preview of the file content."""
|
|
try:
|
|
# Get admin user for workflow operations
|
|
interfaceBase = getInterfaceLucydom(currentUser)
|
|
|
|
# Get file metadata
|
|
file = interfaceBase.getFile(fileId)
|
|
if not file:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"File with ID {fileId} not found"
|
|
)
|
|
|
|
# Get file data (limited for preview)
|
|
fileData = interfaceBase.getFileData(fileId)
|
|
if fileData is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"File data not found for file ID {fileId}"
|
|
)
|
|
|
|
# For text-based files, return a preview of the content
|
|
mimeType = file.get("mimeType", "application/octet-stream")
|
|
isText = mimeType.startswith("text/") or mimeType in [
|
|
"application/json",
|
|
"application/xml",
|
|
"application/javascript"
|
|
]
|
|
|
|
previewData = None
|
|
|
|
# Get base64Encoded flag from database
|
|
fileDataEntries = interfaceBase.db.getRecordset("fileData", recordFilter={"id": fileId})
|
|
if fileDataEntries and "base64Encoded" in fileDataEntries[0]:
|
|
# Use the flag from the database
|
|
base64Encoded = fileDataEntries[0]["base64Encoded"]
|
|
else:
|
|
# Determine based on file type (fallback for older data)
|
|
base64Encoded = not isText
|
|
|
|
if isText:
|
|
# Convert to string without trim for preview
|
|
if isinstance(fileData, bytes):
|
|
try:
|
|
filePreview = fileData.decode('utf-8')
|
|
previewData = filePreview
|
|
except UnicodeDecodeError:
|
|
# Try other encodings
|
|
for encoding in ['latin-1', 'cp1252', 'iso-8859-1']:
|
|
try:
|
|
filePreview = fileData.decode(encoding)
|
|
previewData = filePreview
|
|
break
|
|
except UnicodeDecodeError:
|
|
continue
|
|
|
|
# For images, return base64 encoded data
|
|
if mimeType.startswith("image/"):
|
|
import base64
|
|
previewData = base64.b64encode(fileData).decode('utf-8')
|
|
base64Encoded = True
|
|
|
|
# Return file metadata with preview and base64Encoded flag
|
|
return {
|
|
"id": fileId,
|
|
"name": file.get("name"),
|
|
"mimeType": mimeType,
|
|
"size": file.get("size"),
|
|
"creationDate": file.get("creationDate"),
|
|
"isPreviewable": isText or mimeType.startswith("image/"),
|
|
"preview": previewData,
|
|
"base64Encoded": base64Encoded
|
|
}
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error previewing file: {str(e)}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Error previewing file: {str(e)}"
|
|
)
|
|
|
|
@router.get("/files/{fileId}/download")
|
|
async def downloadFile(
|
|
fileId: str = Path(..., description="ID of the file to download"),
|
|
currentUser: Dict[str, Any] = Depends(getCurrentActiveUser)
|
|
):
|
|
"""Download a file."""
|
|
try:
|
|
# Get admin user for workflow operations
|
|
interfaceBase = getInterfaceLucydom(currentUser)
|
|
|
|
# Get file data
|
|
fileInfo = interfaceBase.downloadFile(fileId)
|
|
if not fileInfo:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"File with ID {fileId} not found"
|
|
)
|
|
|
|
# Return file as response
|
|
return Response(
|
|
content=fileInfo["content"],
|
|
media_type=fileInfo["contentType"],
|
|
headers={
|
|
"Content-Disposition": f"attachment; filename={fileInfo['name']}"
|
|
}
|
|
)
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error downloading file: {str(e)}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Error downloading file: {str(e)}"
|
|
)
|
|
|
|
@router.get("/workflows", response_model=List[Dict[str, Any]])
|
|
async def getWorkflows(currentUser: Dict[str, Any] = Depends(getCurrentActiveUser)):
|
|
"""Get all workflows for the mandate."""
|
|
try:
|
|
# Get admin user for workflow operations
|
|
interfaceBase = getInterfaceLucydom(currentUser)
|
|
|
|
# Get all workflows for the mandate
|
|
workflows = interfaceBase.getWorkflowsByMandate(currentUser.get("_mandateId"))
|
|
return workflows
|
|
except Exception as e:
|
|
logger.error(f"Error getting workflows: {str(e)}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Error getting workflows: {str(e)}"
|
|
)
|
|
|
|
@router.post("/workflows", response_model=Dict[str, Any])
|
|
async def createWorkflow(
|
|
workflow: Dict[str, Any],
|
|
currentUser: Dict[str, Any] = Depends(getCurrentActiveUser)
|
|
):
|
|
"""Create a new workflow."""
|
|
try:
|
|
# Get admin user for workflow operations
|
|
interfaceBase = getInterfaceLucydom(currentUser)
|
|
|
|
# Create workflow
|
|
newWorkflow = interfaceBase.createWorkflow(workflow)
|
|
return newWorkflow
|
|
except Exception as e:
|
|
logger.error(f"Error creating workflow: {str(e)}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Error creating workflow: {str(e)}"
|
|
)
|
|
|
|
@router.get("/workflows/{workflowId}", response_model=Dict[str, Any])
|
|
async def getWorkflow(
|
|
workflowId: str = Path(..., description="ID of the workflow"),
|
|
currentUser: Dict[str, Any] = Depends(getCurrentActiveUser)
|
|
):
|
|
"""Get a specific workflow."""
|
|
try:
|
|
# Get admin user for workflow operations
|
|
interfaceBase = getInterfaceLucydom(currentUser)
|
|
|
|
# Get workflow
|
|
workflow = interfaceBase.getWorkflow(workflowId)
|
|
if not workflow:
|
|
raise HTTPException(status_code=404, detail="Workflow not found")
|
|
|
|
return workflow
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error getting workflow: {str(e)}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Error getting workflow: {str(e)}"
|
|
)
|
|
|
|
@router.put("/workflows/{workflowId}", response_model=Dict[str, Any])
|
|
async def updateWorkflow(
|
|
workflow: Dict[str, Any],
|
|
workflowId: str = Path(..., description="ID of the workflow to update"),
|
|
currentUser: Dict[str, Any] = Depends(getCurrentActiveUser)
|
|
):
|
|
"""Update an existing workflow."""
|
|
try:
|
|
# Get admin user for workflow operations
|
|
interfaceBase = getInterfaceLucydom(currentUser)
|
|
|
|
# Get workflow
|
|
existingWorkflow = interfaceBase.getWorkflow(workflowId)
|
|
if not existingWorkflow:
|
|
raise HTTPException(status_code=404, detail="Workflow not found")
|
|
|
|
# Update workflow
|
|
updatedWorkflow = interfaceBase.updateWorkflow(workflowId, workflow)
|
|
return updatedWorkflow
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error updating workflow: {str(e)}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Error updating workflow: {str(e)}"
|
|
)
|
|
|
|
@router.delete("/workflows/{workflowId}")
|
|
async def deleteWorkflow(
|
|
workflowId: str = Path(..., description="ID of the workflow to delete"),
|
|
currentUser: Dict[str, Any] = Depends(getCurrentActiveUser)
|
|
):
|
|
"""Delete a workflow."""
|
|
try:
|
|
# Get admin user for workflow operations
|
|
interfaceBase = getInterfaceLucydom(currentUser)
|
|
|
|
# Get workflow
|
|
workflow = interfaceBase.getWorkflow(workflowId)
|
|
if not workflow:
|
|
raise HTTPException(status_code=404, detail="Workflow not found")
|
|
|
|
# Delete workflow
|
|
success = interfaceBase.deleteWorkflow(workflowId)
|
|
if not success:
|
|
raise HTTPException(status_code=500, detail="Failed to delete workflow")
|
|
|
|
return {"status": "success"}
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error deleting workflow: {str(e)}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Error deleting workflow: {str(e)}"
|
|
)
|
|
|
|
@router.post("/workflows/{workflowId}/files/{fileId}")
|
|
async def addFileToWorkflow(
|
|
workflowId: str = Path(..., description="ID of the workflow"),
|
|
fileId: str = Path(..., description="ID of the file to add"),
|
|
currentUser: Dict[str, Any] = Depends(getCurrentActiveUser)
|
|
):
|
|
"""Add a file to a workflow."""
|
|
try:
|
|
# Get admin user for workflow operations
|
|
interfaceBase = getInterfaceLucydom(currentUser)
|
|
|
|
# Get workflow
|
|
workflow = interfaceBase.getWorkflow(workflowId)
|
|
if not workflow:
|
|
raise HTTPException(status_code=404, detail="Workflow not found")
|
|
|
|
# Get file
|
|
file = interfaceBase.getFile(fileId)
|
|
if not file:
|
|
raise HTTPException(status_code=404, detail="File not found")
|
|
|
|
# Add file to workflow
|
|
success = interfaceBase.addFileToWorkflow(workflowId, fileId)
|
|
if not success:
|
|
raise HTTPException(status_code=500, detail="Failed to add file to workflow")
|
|
|
|
return {"status": "success"}
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
logger.error(f"Error adding file to workflow: {str(e)}", exc_info=True)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=f"Error adding file to workflow: {str(e)}"
|
|
) |