Spaces:
Sleeping
Sleeping
| from fastapi import APIRouter, HTTPException, Depends, Header | |
| from typing import Optional | |
| from api.models.schemas import ( | |
| UserRegistration, UserCredentials, UserProfileUpdate, | |
| PasswordChange, TokenResponse, AuthResponse, UserProfile, | |
| Conversation, ConversationDetail | |
| ) | |
| from api.services.auth_service import auth_service | |
| router = APIRouter(tags=["auth"]) | |
| # ── Dependency for protected routes ──────────────────────────────────────────── | |
| def get_current_user(authorization: Optional[str] = Header(None)): | |
| """Extract user from JWT token""" | |
| if not authorization: | |
| raise HTTPException(status_code=401, detail="Missing authorization header") | |
| try: | |
| scheme, token = authorization.split() | |
| if scheme.lower() != "bearer": | |
| raise HTTPException(status_code=401, detail="Invalid auth scheme") | |
| except ValueError: | |
| raise HTTPException(status_code=401, detail="Invalid authorization header") | |
| payload = auth_service.verify_token(token) | |
| if not payload: | |
| raise HTTPException(status_code=401, detail="Invalid or expired token") | |
| return payload | |
| # ──────────────────────────────────────────────────────────────────────────────── | |
| # PUBLIC ENDPOINTS | |
| # ──────────────────────────────────────────────────────────────────────────────── | |
| async def register(user_data: UserRegistration): | |
| """Register new user""" | |
| success, message, user_id = auth_service.register_user( | |
| email=user_data.email, | |
| password=user_data.password, | |
| full_name=user_data.full_name, | |
| dob=user_data.dob, | |
| sex=user_data.sex, | |
| medical_history=user_data.medical_history, | |
| geolocation=user_data.geolocation | |
| ) | |
| if not success: | |
| raise HTTPException(status_code=400, detail=message) | |
| return AuthResponse( | |
| success=True, | |
| message=message, | |
| data={"user_id": user_id} | |
| ) | |
| async def login(credentials: UserCredentials): | |
| """Login user and return JWT token""" | |
| success, message, user_data = auth_service.login_user( | |
| email=credentials.email, | |
| password=credentials.password | |
| ) | |
| if not success: | |
| raise HTTPException(status_code=401, detail=message) | |
| access_token = auth_service.create_access_token( | |
| user_id=user_data["user_id"], | |
| email=user_data["email"] | |
| ) | |
| return TokenResponse( | |
| access_token=access_token, | |
| user=UserProfile(**user_data) | |
| ) | |
| # ──────────────────────────────────────────────────────────────────────────────── | |
| # PROTECTED ENDPOINTS | |
| # ──────────────────────────────────────────────────────────────────────────────── | |
| async def get_profile(current_user=Depends(get_current_user)): | |
| """Get current user profile""" | |
| user_data = auth_service.get_user_by_id(current_user["sub"]) | |
| if not user_data: | |
| raise HTTPException(status_code=404, detail="User not found") | |
| return UserProfile(**user_data) | |
| async def update_profile( | |
| profile_data: UserProfileUpdate, | |
| current_user=Depends(get_current_user) | |
| ): | |
| """Update user profile""" | |
| success, message = auth_service.update_user_profile( | |
| user_id=current_user["sub"], | |
| email=profile_data.email, | |
| full_name=profile_data.full_name, | |
| dob=profile_data.dob, | |
| sex=profile_data.sex, | |
| medical_history=profile_data.medical_history, | |
| geolocation=profile_data.geolocation | |
| ) | |
| if not success: | |
| raise HTTPException(status_code=400, detail=message) | |
| return AuthResponse(success=True, message=message) | |
| async def change_password( | |
| pwd_change: PasswordChange, | |
| current_user=Depends(get_current_user) | |
| ): | |
| """Change user password""" | |
| success, message = auth_service.change_password( | |
| user_id=current_user["sub"], | |
| old_password=pwd_change.old_password, | |
| new_password=pwd_change.new_password | |
| ) | |
| if not success: | |
| raise HTTPException(status_code=400, detail=message) | |
| return AuthResponse(success=True, message=message) | |
| async def delete_account( | |
| password: str, | |
| current_user=Depends(get_current_user) | |
| ): | |
| """Delete user account""" | |
| success, message = auth_service.delete_user( | |
| user_id=current_user["sub"], | |
| password=password | |
| ) | |
| if not success: | |
| raise HTTPException(status_code=400, detail=message) | |
| return AuthResponse(success=True, message=message) | |
| # ──────────────────────────────────────────────────────────────────────────────── | |
| # CONVERSATION ENDPOINTS | |
| # ──────────────────────────────────────────────────────────────────────────────── | |
| async def create_conversation( | |
| title: Optional[str] = None, | |
| current_user=Depends(get_current_user) | |
| ): | |
| """Create new conversation""" | |
| success, message, conversation_id = auth_service.create_conversation( | |
| user_id=current_user["sub"], | |
| title=title or "New Conversation" | |
| ) | |
| if not success: | |
| raise HTTPException(status_code=400, detail=message) | |
| return AuthResponse( | |
| success=True, | |
| message=message, | |
| data={"conversation_id": conversation_id} | |
| ) | |
| async def get_conversations(current_user=Depends(get_current_user)): | |
| """Get all user conversations""" | |
| success, message, conversations = auth_service.get_conversations(current_user["sub"]) | |
| if not success: | |
| raise HTTPException(status_code=400, detail=message) | |
| return { | |
| "success": True, | |
| "message": message, | |
| "conversations": conversations | |
| } | |
| async def delete_conversation( | |
| conversation_id: str, | |
| current_user=Depends(get_current_user) | |
| ): | |
| """Delete conversation""" | |
| success, message = auth_service.delete_conversation( | |
| user_id=current_user["sub"], | |
| conversation_id=conversation_id | |
| ) | |
| if not success: | |
| raise HTTPException(status_code=400, detail=message) | |
| return AuthResponse(success=True, message=message) | |
| async def get_conversation_detail( | |
| conversation_id: str, | |
| current_user=Depends(get_current_user) | |
| ): | |
| """Get conversation detail with all messages and diagnosis""" | |
| from api.services.database_interface import conversation_db | |
| conv_data = auth_service._load_conversation(current_user["sub"], conversation_id) | |
| if not conv_data: | |
| raise HTTPException(status_code=404, detail="Conversation not found") | |
| # Load messages from JSONL | |
| messages = conversation_db.get_conversation_messages( | |
| current_user["sub"], | |
| conversation_id | |
| ) | |
| # Load diagnosis if exists | |
| diagnosis_data = conversation_db.get_diagnosis_from_conversation( | |
| current_user["sub"], | |
| conversation_id | |
| ) | |
| return { | |
| "conversation_id": conversation_id, | |
| "title": conv_data.get("title"), | |
| "created_at": conv_data.get("created_at"), | |
| "messages": messages, | |
| "diagnosis": diagnosis_data.get("diagnosis") if diagnosis_data else None, | |
| "recommendations": diagnosis_data.get("recommendations") if diagnosis_data else None | |
| } |