""" Metadata API Endpoints Handles metadata updates and verification. """ from fastapi import APIRouter, Depends, HTTPException, Request, status from sqlalchemy.ext.asyncio import AsyncSession from app.core.auth import get_current_user_id from app.core.database import get_db, AuditLogRepository from app.core.redis_client import RedisSessionStore from app.services.metadata_service import get_metadata_service, MetadataService from app.models.file import ( FileMetadataUpdate, BatchMetadataUpdate, MetadataUpdateResponse ) router = APIRouter() @router.put("/{file_id}") async def update_file_metadata( file_id: str, update_data: FileMetadataUpdate, request: Request, user_id: int = Depends(get_current_user_id), db: AsyncSession = Depends(get_db), metadata_service: MetadataService = Depends(get_metadata_service) ): """ Update metadata for a single file. """ # Get file session redis: RedisSessionStore = request.app.state.redis session_data = await redis.get_file_session(update_data.session_id) if not session_data or session_data.get("user_id") != user_id: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Session not found or access denied" ) # Get file from session files = session_data.get("files", []) if update_data.file_index >= len(files): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid file index" ) file_info = files[update_data.file_index] if file_info.get("file_id") != file_id: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="File ID mismatch" ) # Update metadata success, message = await metadata_service.update_file_metadata( filepath=file_info["filepath"], metadata=update_data.metadata.dict(exclude_none=True) ) if not success: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=message ) # Update session with new metadata file_info["suggested_metadata"] = update_data.metadata.dict(exclude_none=True) files[update_data.file_index] = file_info await redis.update_file_session(update_data.session_id, files) # Log action await AuditLogRepository.log_action( db, user_id=user_id, action="metadata_update", details=f"Updated metadata for file: {file_info['filename']}" ) return MetadataUpdateResponse( success=True, file_id=file_id, filename=file_info["filename"], verified="verified" in message.lower(), message=message ) @router.post("/batch-update") async def batch_update_metadata( update_data: BatchMetadataUpdate, request: Request, user_id: int = Depends(get_current_user_id), db: AsyncSession = Depends(get_db), metadata_service: MetadataService = Depends(get_metadata_service) ): """ Update metadata for multiple files with same metadata. """ # Get file session redis: RedisSessionStore = request.app.state.redis session_data = await redis.get_file_session(update_data.session_id) if not session_data or session_data.get("user_id") != user_id: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Session not found or access denied" ) # Get files from session files = session_data.get("files", []) # Update each file results = [] metadata_dict = update_data.metadata.dict(exclude_none=True) for file_index in update_data.file_indices: if file_index >= len(files): continue file_info = files[file_index] try: # Update metadata success, message = await metadata_service.update_file_metadata( filepath=file_info["filepath"], metadata=metadata_dict ) results.append({ "file_id": file_info["file_id"], "filename": file_info["filename"], "success": success, "message": message }) # Update session if success: file_info["suggested_metadata"] = metadata_dict files[file_index] = file_info except Exception as e: results.append({ "file_id": file_info.get("file_id"), "filename": file_info.get("filename"), "success": False, "message": str(e) }) # Update session with new metadata await redis.update_file_session(update_data.session_id, files) # Log action await AuditLogRepository.log_action( db, user_id=user_id, action="batch_metadata_update", details=f"Updated metadata for {len(update_data.file_indices)} files" ) return { "success": True, "results": results, "message": f"Updated {len(results)} files" }