Spaces:
Runtime error
Runtime error
feat: synchronize text-to-sql-bot codebase with Hugging Face Space repository, including Docker build configurations
6086e71 | """ | |
| Auth, Schema, Analytics, and Health Routes. | |
| """ | |
| from fastapi import APIRouter, Depends, HTTPException, status | |
| from app.api.schemas import ( | |
| LoginRequest, RegisterRequest, TokenResponse, | |
| APIKeyRequest, APIKeyResponse, | |
| SchemaResponse, AnalyticsResponse, HealthResponse, | |
| ) | |
| router = APIRouter(tags=["System"]) | |
| def create_system_router(auth_service, auth_dep, db_pool, rag_retriever, llm_router, tracer, user_repo, start_time): | |
| """Factory to create system routes with injected dependencies.""" | |
| # ββ Auth Routes ββββββββββββββββββββββββββββββββββββββ | |
| auth_router = APIRouter(prefix="/api/v1/auth", tags=["Authentication"]) | |
| def login(request: LoginRequest): | |
| """Authenticate and get JWT token.""" | |
| user = user_repo.get_by_username(request.username) | |
| if not user or not auth_service.verify_password(request.password, user["password_hash"]): | |
| raise HTTPException( | |
| status_code=status.HTTP_401_UNAUTHORIZED, | |
| detail="Invalid username or password", | |
| ) | |
| token = auth_service.create_access_token( | |
| user_id=user["id"], | |
| username=user["username"], | |
| role=user["role"], | |
| tenant_id=user.get("tenant_id", "default"), | |
| ) | |
| return TokenResponse( | |
| access_token=token, | |
| role=user["role"], | |
| tenant_id=user.get("tenant_id", "default"), | |
| ) | |
| def register(request: RegisterRequest): | |
| """Register a new user. Self-registration is always 'viewer' role. | |
| Only admins can promote users via a separate endpoint.""" | |
| if user_repo.get_by_username(request.username): | |
| raise HTTPException(400, "Username already exists") | |
| password_hash = auth_service.hash_password(request.password) | |
| user_id = f"user_{user_repo.count() + 1}" | |
| # SECURITY: Self-registration is always viewer. | |
| # Elevated roles (analyst, admin) must be granted by an existing admin. | |
| assigned_role = "viewer" | |
| success = user_repo.create( | |
| user_id=user_id, | |
| username=request.username, | |
| email=request.email, | |
| password_hash=password_hash, | |
| role=assigned_role, | |
| tenant_id=request.tenant_id, | |
| ) | |
| if not success: | |
| raise HTTPException(500, "Failed to register user") | |
| token = auth_service.create_access_token( | |
| user_id=user_id, | |
| username=request.username, | |
| role=assigned_role, | |
| tenant_id=request.tenant_id, | |
| ) | |
| return TokenResponse( | |
| access_token=token, | |
| role=assigned_role, | |
| tenant_id=request.tenant_id, | |
| ) | |
| def create_api_key(request: APIKeyRequest, current_user: dict = Depends(auth_dep)): | |
| """Create a long-lived API key (admin only).""" | |
| if current_user.get("role") != "admin": | |
| raise HTTPException(403, "Only admins can create API keys") | |
| api_key = auth_service.create_api_key_token( | |
| key_name=request.key_name, | |
| tenant_id=current_user.get("tenant_id", "default"), | |
| role=request.role, | |
| ) | |
| return APIKeyResponse( | |
| key_name=request.key_name, | |
| api_key=api_key, | |
| role=request.role, | |
| ) | |
| # ββ Schema Route βββββββββββββββββββββββββββββββββββββ | |
| schema_router = APIRouter(prefix="/api/v1", tags=["Schema"]) | |
| def get_schema(current_user: dict = Depends(auth_dep)): | |
| """Get database schema for the current tenant.""" | |
| tables = db_pool.get_tables() | |
| schema_text = db_pool.get_full_schema() | |
| return SchemaResponse( | |
| tables=tables, | |
| schema_text=schema_text, | |
| table_count=len(tables), | |
| ) | |
| def refresh_schema(current_user: dict = Depends(auth_dep)): | |
| """Re-index the schema (admin only).""" | |
| if current_user.get("role") != "admin": | |
| raise HTTPException(403, "Only admins can refresh schema") | |
| rag_retriever.refresh_index() | |
| return {"message": "Schema re-indexed successfully"} | |
| # ββ Analytics Route ββββββββββββββββββββββββββββββββββ | |
| analytics_router = APIRouter(prefix="/api/v1", tags=["Analytics"]) | |
| def get_analytics(current_user: dict = Depends(auth_dep)): | |
| """Get usage analytics and metrics.""" | |
| if current_user.get("role") not in ("admin", "analyst"): | |
| raise HTTPException(403, "Insufficient permissions for analytics") | |
| dashboard = tracer.get_dashboard_metrics() | |
| return AnalyticsResponse(**dashboard) | |
| # ββ Health Route βββββββββββββββββββββββββββββββββββββ | |
| health_router = APIRouter(tags=["Health"]) | |
| def health_check(): | |
| """System health check β no auth required.""" | |
| import time as _time | |
| try: | |
| db_status = "connected" | |
| db_pool.get_tables() | |
| except Exception: | |
| db_status = "disconnected" | |
| try: | |
| provider_status = llm_router.get_provider_status() | |
| except Exception: | |
| provider_status = {} | |
| try: | |
| rag_count = rag_retriever.collection.count() | |
| except Exception: | |
| rag_count = 0 | |
| return HealthResponse( | |
| status="healthy" if db_status == "connected" else "degraded", | |
| version="2.0.0", | |
| database=db_status, | |
| llm_providers=provider_status, | |
| rag_indexed_tables=rag_count, | |
| uptime_seconds=round(_time.time() - start_time, 2), | |
| ) | |
| # NOTE: Prometheus metrics endpoint moved to /api/v1/metrics/prometheus | |
| # in monitoring.py to avoid duplicate metrics systems. | |
| def pool_status(current_user: dict = Depends(auth_dep)): | |
| """Database connection pool statistics (admin only).""" | |
| if current_user.get("role") != "admin": | |
| raise HTTPException(403, "Only admins can view pool status") | |
| try: | |
| return db_pool.get_pool_status() | |
| except Exception as e: | |
| return {"error": str(e)} | |
| def list_prompt_templates(current_user: dict = Depends(auth_dep)): | |
| """List all registered prompt templates and their versions (admin only).""" | |
| if current_user.get("role") != "admin": | |
| raise HTTPException(403, "Only admins can view prompt templates") | |
| from app.prompts.registry import get_prompt_registry | |
| return get_prompt_registry().list_templates() | |
| return auth_router, schema_router, analytics_router, health_router | |