File size: 5,719 Bytes
792ad00 951d5c6 792ad00 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | from fastapi import APIRouter, Depends, UploadFile, File, HTTPException
from typing import List
from sqlalchemy.orm import Session
from services.s3_service import s3_service
from api.auth import get_current_user
from core.database import get_db
from models import db_models
from models.schemas import SourceFileResponse
from services.rag_service import rag_service
router = APIRouter(prefix="/api/sources", tags=["sources"])
@router.post("/upload", response_model=dict)
async def upload_source(
file: UploadFile = File(...),
current_user: db_models.User = Depends(get_current_user),
db: Session = Depends(get_db)
):
try:
content = await file.read()
file_info = await s3_service.upload_file(
file_content=content,
filename=file.filename,
user_id=str(current_user.id)
)
# Save metadata to database
db_source = db_models.Source(
filename=file.filename,
s3_key=file_info["key"],
s3_url=file_info["public_url"], # Store public URL in DB
size=len(content),
user_id=current_user.id
)
db.add(db_source)
db.commit()
db.refresh(db_source)
return {
"id": db_source.id,
"filename": file.filename,
"key": file_info["key"],
"public_url": file_info["public_url"],
"private_url": file_info["private_url"],
"message": "Upload successful"
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/list", response_model=List[SourceFileResponse])
async def list_sources(
current_user: db_models.User = Depends(get_current_user),
db: Session = Depends(get_db)
):
try:
# Join Source with RAGDocument to get indexing info if it exists
results = db.query(
db_models.Source,
db_models.RAGDocument.id.label("rag_id"),
db_models.RAGDocument.azure_doc_id
).outerjoin(
db_models.RAGDocument,
db_models.Source.id == db_models.RAGDocument.source_id
).filter(
db_models.Source.user_id == current_user.id
).all()
response_sources = []
for source, rag_id, azure_doc_id in results:
response_sources.append({
"id": source.id,
"filename": source.filename,
"s3_key": source.s3_key,
"public_url": source.s3_url,
"private_url": s3_service.get_presigned_url(source.s3_key),
"size": source.size,
"created_at": source.created_at,
"rag_id": rag_id,
"azure_doc_id": azure_doc_id
})
return response_sources
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.delete("/{source_id}")
async def delete_source(
source_id: int,
current_user: db_models.User = Depends(get_current_user),
db: Session = Depends(get_db)
):
source = db.query(db_models.Source).filter(
db_models.Source.id == source_id,
db_models.Source.user_id == current_user.id
).first()
if not source:
raise HTTPException(status_code=404, detail="Source not found")
try:
# 1. Handle RAG Document (Delete completely as it's useless without the source)
rag_doc = db.query(db_models.RAGDocument).filter(
db_models.RAGDocument.source_id == source.id
).first()
if rag_doc:
# Delete from Azure Search
rag_service.delete_document(rag_doc.azure_doc_id)
# Delete from DB
db.delete(rag_doc)
# 2. Handle other dependencies (Delete everything linked to this source)
# We must delete children (Flashcards, Questions) before parents (Sets) because of SQL constraints
# Delete Flashcards
flashcard_set_ids = [s.id for s in db.query(db_models.FlashcardSet).filter(db_models.FlashcardSet.source_id == source.id).all()]
if flashcard_set_ids:
db.query(db_models.Flashcard).filter(db_models.Flashcard.flashcard_set_id.in_(flashcard_set_ids)).delete(synchronize_session=False)
# Delete Quiz Questions
quiz_set_ids = [s.id for s in db.query(db_models.QuizSet).filter(db_models.QuizSet.source_id == source.id).all()]
if quiz_set_ids:
db.query(db_models.QuizQuestion).filter(db_models.QuizQuestion.quiz_set_id.in_(quiz_set_ids)).delete(synchronize_session=False)
# Now delete the sets and other items
db.query(db_models.MindMap).filter(db_models.MindMap.source_id == source.id).delete()
db.query(db_models.FlashcardSet).filter(db_models.FlashcardSet.source_id == source.id).delete()
db.query(db_models.QuizSet).filter(db_models.QuizSet.source_id == source.id).delete()
db.query(db_models.Report).filter(db_models.Report.source_id == source.id).delete()
db.query(db_models.VideoSummary).filter(db_models.VideoSummary.source_id == source.id).delete()
db.commit() # Commit deletions
# 3. Delete from S3 if it exists
if source.s3_key:
await s3_service.delete_file(source.s3_key)
# 4. Delete the Source itself from Database
db.delete(source)
db.commit()
return {"message": "Source and all associated generated content (mind maps, quizzes, etc.) deleted successfully."}
except Exception as e:
db.rollback()
raise HTTPException(status_code=500, detail=f"Failed to delete source: {str(e)}")
|