This commit is contained in:
Timothy Jaeryang Baek
2026-03-17 17:58:01 -05:00
parent fcf7208352
commit de3317e26b
220 changed files with 17200 additions and 22836 deletions
+125 -217
View File
@@ -73,14 +73,14 @@ def _is_text_file(file_path: str, chunk_size: int = 8192) -> bool:
"""
try:
resolved = Storage.get_file(file_path)
with open(resolved, "rb") as f:
with open(resolved, 'rb') as f:
chunk = f.read(chunk_size)
if not chunk:
return False
# Null bytes are a strong indicator of binary content
if b"\x00" in chunk:
if b'\x00' in chunk:
return False
chunk.decode("utf-8")
chunk.decode('utf-8')
return True
except (UnicodeDecodeError, Exception):
return False
@@ -100,31 +100,25 @@ def process_uploaded_file(
content_type = file.content_type
# Detect mis-labeled text files (e.g. .ts → video/mp2t)
if content_type and content_type.startswith(("image/", "video/")):
if content_type and content_type.startswith(('image/', 'video/')):
if _is_text_file(file_path):
content_type = "text/plain"
content_type = 'text/plain'
if content_type:
stt_supported_content_types = getattr(
request.app.state.config, "STT_SUPPORTED_CONTENT_TYPES", []
)
stt_supported_content_types = getattr(request.app.state.config, 'STT_SUPPORTED_CONTENT_TYPES', [])
if strict_match_mime_type(stt_supported_content_types, content_type):
file_path_processed = Storage.get_file(file_path)
result = transcribe(
request, file_path_processed, file_metadata, user
)
result = transcribe(request, file_path_processed, file_metadata, user)
process_file(
request,
ProcessFileForm(
file_id=file_item.id, content=result.get("text", "")
),
ProcessFileForm(file_id=file_item.id, content=result.get('text', '')),
user=user,
db=db_session,
)
elif (not content_type.startswith(("image/", "video/"))) or (
request.app.state.config.CONTENT_EXTRACTION_ENGINE == "external"
elif (not content_type.startswith(('image/', 'video/'))) or (
request.app.state.config.CONTENT_EXTRACTION_ENGINE == 'external'
):
process_file(
request,
@@ -133,13 +127,9 @@ def process_uploaded_file(
db=db_session,
)
else:
raise Exception(
f"File type {content_type} is not supported for processing"
)
raise Exception(f'File type {content_type} is not supported for processing')
else:
log.info(
f"File type {file.content_type} is not provided, but trying to process anyway"
)
log.info(f'File type {file.content_type} is not provided, but trying to process anyway')
process_file(
request,
ProcessFileForm(file_id=file_item.id),
@@ -148,12 +138,12 @@ def process_uploaded_file(
)
except Exception as e:
log.error(f"Error processing file: {file_item.id}")
log.error(f'Error processing file: {file_item.id}')
Files.update_file_data_by_id(
file_item.id,
{
"status": "failed",
"error": str(e.detail) if hasattr(e, "detail") else str(e),
'status': 'failed',
'error': str(e.detail) if hasattr(e, 'detail') else str(e),
},
db=db_session,
)
@@ -165,7 +155,7 @@ def process_uploaded_file(
_process_handler(db_session)
@router.post("/", response_model=FileModelResponse)
@router.post('/', response_model=FileModelResponse)
def upload_file(
request: Request,
background_tasks: BackgroundTasks,
@@ -198,7 +188,7 @@ def upload_file_handler(
background_tasks: Optional[BackgroundTasks] = None,
db: Optional[Session] = None,
):
log.info(f"file.content_type: {file.content_type} {process}")
log.info(f'file.content_type: {file.content_type} {process}')
if isinstance(metadata, str):
try:
@@ -206,7 +196,7 @@ def upload_file_handler(
except json.JSONDecodeError:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.DEFAULT("Invalid metadata format"),
detail=ERROR_MESSAGES.DEFAULT('Invalid metadata format'),
)
file_metadata = metadata if metadata else {}
@@ -216,7 +206,7 @@ def upload_file_handler(
file_extension = os.path.splitext(filename)[1]
# Remove the leading dot from the file extension
file_extension = file_extension[1:] if file_extension else ""
file_extension = file_extension[1:] if file_extension else ''
if process and request.app.state.config.ALLOWED_FILE_EXTENSIONS:
request.app.state.config.ALLOWED_FILE_EXTENSIONS = [
@@ -226,23 +216,21 @@ def upload_file_handler(
if file_extension not in request.app.state.config.ALLOWED_FILE_EXTENSIONS:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.DEFAULT(
f"File type {file_extension} is not allowed"
),
detail=ERROR_MESSAGES.DEFAULT(f'File type {file_extension} is not allowed'),
)
# replace filename with uuid
id = str(uuid.uuid4())
name = filename
filename = f"{id}_{filename}"
filename = f'{id}_{filename}'
contents, file_path = Storage.upload_file(
file.file,
filename,
{
"OpenWebUI-User-Email": user.email,
"OpenWebUI-User-Id": user.id,
"OpenWebUI-User-Name": user.name,
"OpenWebUI-File-Id": id,
'OpenWebUI-User-Email': user.email,
'OpenWebUI-User-Id': user.id,
'OpenWebUI-User-Name': user.name,
'OpenWebUI-File-Id': id,
},
)
@@ -250,35 +238,27 @@ def upload_file_handler(
user.id,
FileForm(
**{
"id": id,
"filename": name,
"path": file_path,
"data": {
**({"status": "pending"} if process else {}),
'id': id,
'filename': name,
'path': file_path,
'data': {
**({'status': 'pending'} if process else {}),
},
"meta": {
"name": name,
"content_type": (
file.content_type
if isinstance(file.content_type, str)
else None
),
"size": len(contents),
"data": file_metadata,
'meta': {
'name': name,
'content_type': (file.content_type if isinstance(file.content_type, str) else None),
'size': len(contents),
'data': file_metadata,
},
}
),
db=db,
)
if "channel_id" in file_metadata:
channel = Channels.get_channel_by_id_and_user_id(
file_metadata["channel_id"], user.id, db=db
)
if 'channel_id' in file_metadata:
channel = Channels.get_channel_by_id_and_user_id(file_metadata['channel_id'], user.id, db=db)
if channel:
Channels.add_file_to_channel_by_id(
channel.id, file_item.id, user.id, db=db
)
Channels.add_file_to_channel_by_id(channel.id, file_item.id, user.id, db=db)
if process:
if background_tasks and process_in_background:
@@ -291,7 +271,7 @@ def upload_file_handler(
file_metadata,
user,
)
return {"status": True, **file_item.model_dump()}
return {'status': True, **file_item.model_dump()}
else:
process_uploaded_file(
request,
@@ -302,14 +282,14 @@ def upload_file_handler(
user,
db=db,
)
return {"status": True, **file_item.model_dump()}
return {'status': True, **file_item.model_dump()}
else:
if file_item:
return file_item
else:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.DEFAULT("Error uploading file"),
detail=ERROR_MESSAGES.DEFAULT('Error uploading file'),
)
except HTTPException as e:
@@ -318,7 +298,7 @@ def upload_file_handler(
log.exception(e)
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.DEFAULT("Error uploading file"),
detail=ERROR_MESSAGES.DEFAULT('Error uploading file'),
)
@@ -330,26 +310,22 @@ def upload_file_handler(
PAGE_SIZE = 50
@router.get("/", response_model=FileListResponse)
@router.get('/', response_model=FileListResponse)
async def list_files(
user=Depends(get_verified_user),
page: int = Query(1, ge=1, description="Page number (1-indexed)"),
page: int = Query(1, ge=1, description='Page number (1-indexed)'),
content: bool = Query(True),
db: Session = Depends(get_session),
):
skip = (page - 1) * PAGE_SIZE
user_id = (
None if (user.role == "admin" and BYPASS_ADMIN_ACCESS_CONTROL) else user.id
)
user_id = None if (user.role == 'admin' and BYPASS_ADMIN_ACCESS_CONTROL) else user.id
result = Files.get_file_list(
user_id=user_id, skip=skip, limit=PAGE_SIZE, db=db
)
result = Files.get_file_list(user_id=user_id, skip=skip, limit=PAGE_SIZE, db=db)
if not content:
for file in result.items:
if file.data and "content" in file.data:
del file.data["content"]
if file.data and 'content' in file.data:
del file.data['content']
return result
@@ -359,17 +335,15 @@ async def list_files(
############################
@router.get("/search", response_model=list[FileModelResponse])
@router.get('/search', response_model=list[FileModelResponse])
async def search_files(
filename: str = Query(
...,
description="Filename pattern to search for. Supports wildcards such as '*.txt'",
),
content: bool = Query(True),
skip: int = Query(0, ge=0, description="Number of files to skip"),
limit: int = Query(
100, ge=1, le=1000, description="Maximum number of files to return"
),
skip: int = Query(0, ge=0, description='Number of files to skip'),
limit: int = Query(100, ge=1, le=1000, description='Maximum number of files to return'),
user=Depends(get_verified_user),
db: Session = Depends(get_session),
):
@@ -378,9 +352,7 @@ async def search_files(
Uses SQL-based filtering with pagination for better performance.
"""
# Determine user_id: null for admin with bypass (search all), user.id otherwise
user_id = (
None if (user.role == "admin" and BYPASS_ADMIN_ACCESS_CONTROL) else user.id
)
user_id = None if (user.role == 'admin' and BYPASS_ADMIN_ACCESS_CONTROL) else user.id
# Use optimized database query with pagination
files = Files.search_files(
@@ -394,13 +366,13 @@ async def search_files(
if not files:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="No files found matching the pattern.",
detail='No files found matching the pattern.',
)
if not content:
for file in files:
if file.data and "content" in file.data:
del file.data["content"]
if file.data and 'content' in file.data:
del file.data['content']
return files
@@ -410,10 +382,8 @@ async def search_files(
############################
@router.delete("/all")
async def delete_all_files(
user=Depends(get_admin_user), db: Session = Depends(get_session)
):
@router.delete('/all')
async def delete_all_files(user=Depends(get_admin_user), db: Session = Depends(get_session)):
result = Files.delete_all_files(db=db)
if result:
try:
@@ -421,16 +391,16 @@ async def delete_all_files(
VECTOR_DB_CLIENT.reset()
except Exception as e:
log.exception(e)
log.error("Error deleting files")
log.error('Error deleting files')
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.DEFAULT("Error deleting files"),
detail=ERROR_MESSAGES.DEFAULT('Error deleting files'),
)
return {"message": "All files deleted successfully"}
return {'message': 'All files deleted successfully'}
else:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.DEFAULT("Error deleting files"),
detail=ERROR_MESSAGES.DEFAULT('Error deleting files'),
)
@@ -439,10 +409,8 @@ async def delete_all_files(
############################
@router.get("/{id}", response_model=Optional[FileModel])
async def get_file_by_id(
id: str, user=Depends(get_verified_user), db: Session = Depends(get_session)
):
@router.get('/{id}', response_model=Optional[FileModel])
async def get_file_by_id(id: str, user=Depends(get_verified_user), db: Session = Depends(get_session)):
file = Files.get_file_by_id(id, db=db)
if not file:
@@ -451,11 +419,7 @@ async def get_file_by_id(
detail=ERROR_MESSAGES.NOT_FOUND,
)
if (
file.user_id == user.id
or user.role == "admin"
or has_access_to_file(id, "read", user, db=db)
):
if file.user_id == user.id or user.role == 'admin' or has_access_to_file(id, 'read', user, db=db):
return file
else:
raise HTTPException(
@@ -464,7 +428,7 @@ async def get_file_by_id(
)
@router.get("/{id}/process/status")
@router.get('/{id}/process/status')
async def get_file_process_status(
id: str,
stream: bool = Query(False),
@@ -479,11 +443,7 @@ async def get_file_process_status(
detail=ERROR_MESSAGES.NOT_FOUND,
)
if (
file.user_id == user.id
or user.role == "admin"
or has_access_to_file(id, "read", user, db=db)
):
if file.user_id == user.id or user.role == 'admin' or has_access_to_file(id, 'read', user, db=db):
if stream:
MAX_FILE_PROCESSING_DURATION = 3600 * 2
@@ -494,32 +454,32 @@ async def get_file_process_status(
for _ in range(MAX_FILE_PROCESSING_DURATION):
file_item = Files.get_file_by_id(file_id) # Creates own session
if file_item:
data = file_item.model_dump().get("data", {})
status = data.get("status")
data = file_item.model_dump().get('data', {})
status = data.get('status')
if status:
event = {"status": status}
if status == "failed":
event["error"] = data.get("error")
event = {'status': status}
if status == 'failed':
event['error'] = data.get('error')
yield f"data: {json.dumps(event)}\n\n"
if status in ("completed", "failed"):
yield f'data: {json.dumps(event)}\n\n'
if status in ('completed', 'failed'):
break
else:
# Legacy
break
else:
yield f"data: {json.dumps({'status': 'not_found'})}\n\n"
yield f'data: {json.dumps({"status": "not_found"})}\n\n'
break
await asyncio.sleep(1)
return StreamingResponse(
event_stream(file.id),
media_type="text/event-stream",
media_type='text/event-stream',
)
else:
return {"status": file.data.get("status", "pending")}
return {'status': file.data.get('status', 'pending')}
else:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
@@ -532,10 +492,8 @@ async def get_file_process_status(
############################
@router.get("/{id}/data/content")
async def get_file_data_content_by_id(
id: str, user=Depends(get_verified_user), db: Session = Depends(get_session)
):
@router.get('/{id}/data/content')
async def get_file_data_content_by_id(id: str, user=Depends(get_verified_user), db: Session = Depends(get_session)):
file = Files.get_file_by_id(id, db=db)
if not file:
@@ -544,12 +502,8 @@ async def get_file_data_content_by_id(
detail=ERROR_MESSAGES.NOT_FOUND,
)
if (
file.user_id == user.id
or user.role == "admin"
or has_access_to_file(id, "read", user, db=db)
):
return {"content": file.data.get("content", "")}
if file.user_id == user.id or user.role == 'admin' or has_access_to_file(id, 'read', user, db=db):
return {'content': file.data.get('content', '')}
else:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
@@ -566,7 +520,7 @@ class ContentForm(BaseModel):
content: str
@router.post("/{id}/data/content/update")
@router.post('/{id}/data/content/update')
def update_file_data_content_by_id(
request: Request,
id: str,
@@ -582,11 +536,7 @@ def update_file_data_content_by_id(
detail=ERROR_MESSAGES.NOT_FOUND,
)
if (
file.user_id == user.id
or user.role == "admin"
or has_access_to_file(id, "write", user, db=db)
):
if file.user_id == user.id or user.role == 'admin' or has_access_to_file(id, 'write', user, db=db):
try:
process_file(
request,
@@ -597,7 +547,7 @@ def update_file_data_content_by_id(
file = Files.get_file_by_id(id=id, db=db)
except Exception as e:
log.exception(e)
log.error(f"Error processing file: {file.id}")
log.error(f'Error processing file: {file.id}')
# Propagate content change to all knowledge collections referencing
# this file. Without this the old embeddings remain in the knowledge
@@ -606,9 +556,7 @@ def update_file_data_content_by_id(
for knowledge in knowledges:
try:
# Remove old embeddings for this file from the KB collection
VECTOR_DB_CLIENT.delete(
collection_name=knowledge.id, filter={"file_id": id}
)
VECTOR_DB_CLIENT.delete(collection_name=knowledge.id, filter={'file_id': id})
# Re-add from the now-updated file-{file_id} collection
process_file(
request,
@@ -617,12 +565,9 @@ def update_file_data_content_by_id(
db=db,
)
except Exception as e:
log.warning(
f"Failed to update knowledge {knowledge.id} after "
f"content change for file {id}: {e}"
)
log.warning(f'Failed to update knowledge {knowledge.id} after content change for file {id}: {e}')
return {"content": file.data.get("content", "")}
return {'content': file.data.get('content', '')}
else:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
@@ -635,7 +580,7 @@ def update_file_data_content_by_id(
############################
@router.get("/{id}/content")
@router.get('/{id}/content')
async def get_file_content_by_id(
id: str,
user=Depends(get_verified_user),
@@ -650,11 +595,7 @@ async def get_file_content_by_id(
detail=ERROR_MESSAGES.NOT_FOUND,
)
if (
file.user_id == user.id
or user.role == "admin"
or has_access_to_file(id, "read", user, db=db)
):
if file.user_id == user.id or user.role == 'admin' or has_access_to_file(id, 'read', user, db=db):
try:
file_path = Storage.get_file(file.path)
file_path = Path(file_path)
@@ -662,30 +603,22 @@ async def get_file_content_by_id(
# Check if the file already exists in the cache
if file_path.is_file():
# Handle Unicode filenames
filename = file.meta.get("name", file.filename)
filename = file.meta.get('name', file.filename)
encoded_filename = quote(filename) # RFC5987 encoding
content_type = file.meta.get("content_type")
filename = file.meta.get("name", file.filename)
content_type = file.meta.get('content_type')
filename = file.meta.get('name', file.filename)
encoded_filename = quote(filename)
headers = {}
if attachment:
headers["Content-Disposition"] = (
f"attachment; filename*=UTF-8''{encoded_filename}"
)
headers['Content-Disposition'] = f"attachment; filename*=UTF-8''{encoded_filename}"
else:
if content_type == "application/pdf" or filename.lower().endswith(
".pdf"
):
headers["Content-Disposition"] = (
f"inline; filename*=UTF-8''{encoded_filename}"
)
content_type = "application/pdf"
elif content_type != "text/plain":
headers["Content-Disposition"] = (
f"attachment; filename*=UTF-8''{encoded_filename}"
)
if content_type == 'application/pdf' or filename.lower().endswith('.pdf'):
headers['Content-Disposition'] = f"inline; filename*=UTF-8''{encoded_filename}"
content_type = 'application/pdf'
elif content_type != 'text/plain':
headers['Content-Disposition'] = f"attachment; filename*=UTF-8''{encoded_filename}"
return FileResponse(file_path, headers=headers, media_type=content_type)
@@ -698,10 +631,10 @@ async def get_file_content_by_id(
raise e
except Exception as e:
log.exception(e)
log.error("Error getting file content")
log.error('Error getting file content')
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.DEFAULT("Error getting file content"),
detail=ERROR_MESSAGES.DEFAULT('Error getting file content'),
)
else:
raise HTTPException(
@@ -710,10 +643,8 @@ async def get_file_content_by_id(
)
@router.get("/{id}/content/html")
async def get_html_file_content_by_id(
id: str, user=Depends(get_verified_user), db: Session = Depends(get_session)
):
@router.get('/{id}/content/html')
async def get_html_file_content_by_id(id: str, user=Depends(get_verified_user), db: Session = Depends(get_session)):
file = Files.get_file_by_id(id, db=db)
if not file:
@@ -723,24 +654,20 @@ async def get_html_file_content_by_id(
)
file_user = Users.get_user_by_id(file.user_id, db=db)
if not file_user.role == "admin":
if not file_user.role == 'admin':
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=ERROR_MESSAGES.NOT_FOUND,
)
if (
file.user_id == user.id
or user.role == "admin"
or has_access_to_file(id, "read", user, db=db)
):
if file.user_id == user.id or user.role == 'admin' or has_access_to_file(id, 'read', user, db=db):
try:
file_path = Storage.get_file(file.path)
file_path = Path(file_path)
# Check if the file already exists in the cache
if file_path.is_file():
log.info(f"file_path: {file_path}")
log.info(f'file_path: {file_path}')
return FileResponse(file_path)
else:
raise HTTPException(
@@ -751,10 +678,10 @@ async def get_html_file_content_by_id(
raise e
except Exception as e:
log.exception(e)
log.error("Error getting file content")
log.error('Error getting file content')
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.DEFAULT("Error getting file content"),
detail=ERROR_MESSAGES.DEFAULT('Error getting file content'),
)
else:
raise HTTPException(
@@ -763,10 +690,8 @@ async def get_html_file_content_by_id(
)
@router.get("/{id}/content/{file_name}")
async def get_file_content_by_id(
id: str, user=Depends(get_verified_user), db: Session = Depends(get_session)
):
@router.get('/{id}/content/{file_name}')
async def get_file_content_by_id(id: str, user=Depends(get_verified_user), db: Session = Depends(get_session)):
file = Files.get_file_by_id(id, db=db)
if not file:
@@ -775,19 +700,13 @@ async def get_file_content_by_id(
detail=ERROR_MESSAGES.NOT_FOUND,
)
if (
file.user_id == user.id
or user.role == "admin"
or has_access_to_file(id, "read", user, db=db)
):
if file.user_id == user.id or user.role == 'admin' or has_access_to_file(id, 'read', user, db=db):
file_path = file.path
# Handle Unicode filenames
filename = file.meta.get("name", file.filename)
filename = file.meta.get('name', file.filename)
encoded_filename = quote(filename) # RFC5987 encoding
headers = {
"Content-Disposition": f"attachment; filename*=UTF-8''{encoded_filename}"
}
headers = {'Content-Disposition': f"attachment; filename*=UTF-8''{encoded_filename}"}
if file_path:
file_path = Storage.get_file(file_path)
@@ -803,16 +722,16 @@ async def get_file_content_by_id(
)
else:
# File path doesn’t exist, return the content as .txt if possible
file_content = file.content.get("content", "")
file_content = file.content.get('content', '')
file_name = file.filename
# Create a generator that encodes the file content
def generator():
yield file_content.encode("utf-8")
yield file_content.encode('utf-8')
return StreamingResponse(
generator(),
media_type="text/plain",
media_type='text/plain',
headers=headers,
)
else:
@@ -827,10 +746,8 @@ async def get_file_content_by_id(
############################
@router.delete("/{id}")
async def delete_file_by_id(
id: str, user=Depends(get_verified_user), db: Session = Depends(get_session)
):
@router.delete('/{id}')
async def delete_file_by_id(id: str, user=Depends(get_verified_user), db: Session = Depends(get_session)):
file = Files.get_file_by_id(id, db=db)
if not file:
@@ -839,12 +756,7 @@ async def delete_file_by_id(
detail=ERROR_MESSAGES.NOT_FOUND,
)
if (
file.user_id == user.id
or user.role == "admin"
or has_access_to_file(id, "write", user, db=db)
):
if file.user_id == user.id or user.role == 'admin' or has_access_to_file(id, 'write', user, db=db):
# Clean up KB associations and embeddings before deleting
knowledges = Knowledges.get_knowledges_by_file_id(id, db=db)
for knowledge in knowledges:
@@ -852,33 +764,29 @@ async def delete_file_by_id(
Knowledges.remove_file_from_knowledge_by_id(knowledge.id, id, db=db)
# Clean KB embeddings (same logic as /knowledge/{id}/file/remove)
try:
VECTOR_DB_CLIENT.delete(
collection_name=knowledge.id, filter={"file_id": id}
)
VECTOR_DB_CLIENT.delete(collection_name=knowledge.id, filter={'file_id': id})
if file.hash:
VECTOR_DB_CLIENT.delete(
collection_name=knowledge.id, filter={"hash": file.hash}
)
VECTOR_DB_CLIENT.delete(collection_name=knowledge.id, filter={'hash': file.hash})
except Exception as e:
log.debug(f"KB embedding cleanup for {knowledge.id}: {e}")
log.debug(f'KB embedding cleanup for {knowledge.id}: {e}')
result = Files.delete_file_by_id(id, db=db)
if result:
try:
Storage.delete_file(file.path)
VECTOR_DB_CLIENT.delete(collection_name=f"file-{id}")
VECTOR_DB_CLIENT.delete(collection_name=f'file-{id}')
except Exception as e:
log.exception(e)
log.error("Error deleting files")
log.error('Error deleting files')
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.DEFAULT("Error deleting files"),
detail=ERROR_MESSAGES.DEFAULT('Error deleting files'),
)
return {"message": "File deleted successfully"}
return {'message': 'File deleted successfully'}
else:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=ERROR_MESSAGES.DEFAULT("Error deleting file"),
detail=ERROR_MESSAGES.DEFAULT('Error deleting file'),
)
else:
raise HTTPException(