from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File from fastapi.responses import FileResponse from sqlalchemy.orm import Session import os import uuid # Pour générer des noms de fichiers uniques from core.database import get_db from core.security import create_access_token # Non utilisé directement ici mais potentiellement dans d'autres routers from core.config import settings # Pour accéder au chemin d'upload from crud import document as crud_document from crud import user as crud_user # Pour récupérer l'utilisateur courant from schemas import document as schemas_document from schemas import user as schemas_user # Pour le modèle UserInDBBase ou UserResponse from dependencies import get_current_user # Pour la protection des routes router = APIRouter( prefix="/documents", tags=["Documents"], responses={404: {"description": "Not found"}}, ) @router.post("/upload-cv", response_model=schemas_document.DocumentResponse, status_code=status.HTTP_201_CREATED) async def upload_cv( file: UploadFile = File(...), db: Session = Depends(get_db), current_user: schemas_user.UserResponse = Depends(get_current_user) ): """ Permet à un utilisateur authentifié d'uploader un CV. Le fichier est stocké sur le serveur et ses métadonnées sont enregistrées en base de données. """ if not file.filename.lower().endswith(('.pdf', '.doc', '.docx')): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Seuls les fichiers PDF, DOC, DOCX sont autorisés." ) # Créer un nom de fichier unique pour éviter les collisions et les problèmes de sécurité unique_filename = f"{uuid.uuid4()}_{file.filename}" file_path = os.path.join(settings.UPLOADS_DIR, unique_filename) # S'assurer que le répertoire d'uploads existe os.makedirs(settings.UPLOADS_DIR, exist_ok=True) try: with open(file_path, "wb") as buffer: # Écrit le fichier par morceaux pour les gros fichiers while content := await file.read(1024 * 1024): # Lire par blocs de 1MB buffer.write(content) except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Erreur lors de l'enregistrement du fichier: {e}" ) finally: await file.close() # Enregistrer les métadonnées du document dans la base de données document_data = schemas_document.DocumentCreate(filename=file.filename) db_document = crud_document.create_document(db, document_data, file_path, current_user.id) return db_document @router.get("/", response_model=list[schemas_document.DocumentResponse]) def get_user_documents( db: Session = Depends(get_db), current_user: schemas_user.UserResponse = Depends(get_current_user) ): """ Récupère tous les documents uploadés par l'utilisateur authentifié. """ documents = crud_document.get_documents_by_owner(db, current_user.id) return documents @router.get("/{document_id}", response_model=schemas_document.DocumentResponse) def get_document_details( document_id: int, db: Session = Depends(get_db), current_user: schemas_user.UserResponse = Depends(get_current_user) ): """ Récupère les détails d'un document spécifique de l'utilisateur authentifié. """ document = crud_document.get_document_by_id(db, document_id) if not document: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Document non trouvé.") if document.owner_id != current_user.id: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Vous n'avez pas accès à ce document.") return document @router.delete("/{document_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_document( document_id: int, db: Session = Depends(get_db), current_user: schemas_user.UserResponse = Depends(get_current_user) ): """ Supprime un document spécifique de l'utilisateur authentifié, à la fois de la base de données et du système de fichiers. """ db_document = crud_document.get_document_by_id(db, document_id) if not db_document: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Document non trouvé.") if db_document.owner_id != current_user.id: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Vous n'avez pas la permission de supprimer ce document.") # Supprimer le fichier du système de fichiers if os.path.exists(db_document.filepath): try: os.remove(db_document.filepath) except OSError as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Erreur lors de la suppression du fichier sur le serveur: {e}" ) # Supprimer l'entrée de la base de données crud_document.delete_document(db, document_id) return {"message": "Document supprimé avec succès."}