# ================================================================ # services/auth/app/api/auth.py (ENHANCED VERSION) # ================================================================ """ Authentication API routes - Enhanced with proper error handling and logging """ from fastapi import APIRouter, Depends, HTTPException, status, Request from sqlalchemy.ext.asyncio import AsyncSession import logging from app.core.database import get_db from app.schemas.auth import ( UserRegistration, UserLogin, TokenResponse, RefreshTokenRequest, UserResponse ) from app.services.auth_service import AuthService from app.core.security import security_manager from shared.monitoring.metrics import MetricsCollector logger = logging.getLogger(__name__) router = APIRouter() metrics = MetricsCollector("auth_service") @router.post("/register", response_model=UserResponse) async def register( user_data: UserRegistration, db: AsyncSession = Depends(get_db) ): """Register a new user""" try: metrics.increment_counter("auth_registration_total") result = await AuthService.register_user(user_data, db) logger.info(f"User registration successful: {user_data.email}") return result except HTTPException: raise except Exception as e: logger.error(f"Registration error for {user_data.email}: {e}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Registration failed" ) @router.post("/login", response_model=TokenResponse) async def login( login_data: UserLogin, request: Request, db: AsyncSession = Depends(get_db) ): """User login""" try: ip_address = request.client.host user_agent = request.headers.get("user-agent", "") result = await AuthService.login_user(login_data, db, ip_address, user_agent) metrics.increment_counter("auth_login_success_total") return result except HTTPException as e: metrics.increment_counter("auth_login_failure_total") logger.warning(f"Login failed for {login_data.email}: {e.detail}") raise except Exception as e: metrics.increment_counter("auth_login_failure_total") logger.error(f"Login error for {login_data.email}: {e}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Login failed" ) @router.post("/refresh", response_model=TokenResponse) async def refresh_token( refresh_data: RefreshTokenRequest, db: AsyncSession = Depends(get_db) ): """Refresh access token""" try: return await AuthService.refresh_token(refresh_data.refresh_token, db) except HTTPException: raise except Exception as e: logger.error(f"Token refresh error: {e}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Token refresh failed" ) @router.post("/verify") async def verify_token( request: Request, db: AsyncSession = Depends(get_db) ): """Verify access token""" try: auth_header = request.headers.get("Authorization") if not auth_header or not auth_header.startswith("Bearer "): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Authorization header required" ) token = auth_header.split(" ")[1] token_data = await AuthService.verify_token(token) return { "valid": True, "user_id": token_data.get("user_id"), "email": token_data.get("email"), "role": token_data.get("role"), "tenant_id": token_data.get("tenant_id") } except HTTPException: raise except Exception as e: logger.error(f"Token verification error: {e}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Token verification failed" ) @router.post("/logout") async def logout( refresh_data: RefreshTokenRequest, request: Request, db: AsyncSession = Depends(get_db) ): """Logout user""" try: # Get user from token auth_header = request.headers.get("Authorization") if auth_header and auth_header.startswith("Bearer "): token = auth_header.split(" ")[1] token_data = await AuthService.verify_token(token) user_id = token_data.get("user_id") if user_id: success = await AuthService.logout_user(user_id, refresh_data.refresh_token, db) return {"success": success} return {"success": False, "message": "Invalid token"} except Exception as e: logger.error(f"Logout error: {e}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Logout failed" )