Spaces:
Sleeping
Sleeping
| from pydantic_settings import BaseSettings | |
| from typing import List, Optional | |
| from urllib.parse import quote_plus | |
| import os | |
| from dotenv import load_dotenv | |
| # Load environment variables from .env file before creating settings | |
| load_dotenv() | |
| # Check environment variables directly to ensure Neon is prioritized | |
| NEON_DATABASE_URL = os.getenv("NEON_DATABASE_URL") | |
| DATABASE_URL = os.getenv("DATABASE_URL") | |
| # Determine the database URL to use - prioritize Neon | |
| FINAL_DATABASE_URL = NEON_DATABASE_URL if NEON_DATABASE_URL else DATABASE_URL | |
| if not FINAL_DATABASE_URL: | |
| # Only fallback to SQLite if neither environment variable is set | |
| FINAL_DATABASE_URL = "sqlite:///./todo_app.db" | |
| class Settings(BaseSettings): | |
| """ | |
| Application settings loaded from environment variables. | |
| """ | |
| # Project information | |
| project_name: str = "Secure Todo API" | |
| version: str = "1.0.0" | |
| description: str = "Secure Multi-User Todo Web Application with JWT Authentication" | |
| # API settings | |
| api_v1_prefix: str = "/api/v1" | |
| # Database settings - use the final determined database URL | |
| database_url: str = FINAL_DATABASE_URL | |
| neon_database_url: Optional[str] = NEON_DATABASE_URL | |
| database_echo: bool = os.getenv("DATABASE_ECHO", "False").lower() == "true" | |
| database_pool_size: int = int(os.getenv("DATABASE_POOL_SIZE", "5")) | |
| database_max_overflow: int = int(os.getenv("DATABASE_MAX_OVERFLOW", "10")) | |
| # JWT settings | |
| secret_key: str = os.getenv("SECRET_KEY", "your-super-secret-jwt-signing-key-here-make-it-long-and-random") | |
| algorithm: str = os.getenv("ALGORITHM", "HS256") | |
| access_token_expire_minutes: int = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", "30")) | |
| refresh_token_expire_days: int = int(os.getenv("REFRESH_TOKEN_EXPIRE_DAYS", "7")) | |
| # CORS settings | |
| backend_cors_origins: List[str] = [ | |
| # Local development | |
| "http://localhost:3000", | |
| "http://localhost:3001", | |
| "http://localhost:8000", | |
| "http://127.0.0.1:3000", | |
| "http://127.0.0.1:8000", | |
| "https://localhost:3000", | |
| # Production - Vercel deployments | |
| "https://multi-tasking-website-red-stal-ler.vercel.app", # Current deployment | |
| "https://multi-tasking-todo-app-hot-h-r-rose.vercel.app", # Previous deployment | |
| "https://*.vercel.app", # Allow all Vercel preview deployments | |
| # Production - Hugging Face | |
| "https://syedfarooqali-todo-app.hf.space", | |
| ] | |
| # Logging settings | |
| log_level: str = os.getenv("LOG_LEVEL", "INFO") | |
| log_format: str = os.getenv("LOG_FORMAT", "%(asctime)s - %(name)s - %(levelname)s - %(message)s") | |
| # Better Auth settings | |
| better_auth_url: str = os.getenv("BETTER_AUTH_URL", "http://localhost:8000") | |
| model_config = { | |
| "env_file": ".env", # This will still be used for other settings | |
| "case_sensitive": True, | |
| "extra": "ignore" | |
| } | |
| # Create settings instance | |
| settings = Settings() | |
| # Error handling and exception handlers | |
| from fastapi import Request, HTTPException | |
| from fastapi.responses import JSONResponse | |
| from starlette.exceptions import HTTPException as StarletteHTTPException | |
| import logging | |
| def setup_logging(): | |
| """ | |
| Configure application logging. | |
| """ | |
| logging.basicConfig( | |
| level=settings.log_level.upper(), | |
| format=settings.log_format | |
| ) | |
| def http_exception_handler(request: Request, exc: HTTPException): | |
| """ | |
| Handle HTTP exceptions and return JSON responses. | |
| """ | |
| return JSONResponse( | |
| status_code=exc.status_code, | |
| content={ | |
| "error": { | |
| "code": f"HTTP_{exc.status_code}", | |
| "message": exc.detail if hasattr(exc, 'detail') else "An error occurred" | |
| } | |
| } | |
| ) | |
| def validation_exception_handler(request: Request, exc: Exception): | |
| """ | |
| Handle validation exceptions and return JSON responses. | |
| """ | |
| return JSONResponse( | |
| status_code=422, | |
| content={ | |
| "error": { | |
| "code": "VALIDATION_ERROR", | |
| "message": "Validation error occurred", | |
| "details": str(exc) | |
| } | |
| } | |
| ) | |
| def general_exception_handler(request: Request, exc: Exception): | |
| """ | |
| Handle general exceptions and return JSON responses. | |
| """ | |
| return JSONResponse( | |
| status_code=500, | |
| content={ | |
| "error": { | |
| "code": "INTERNAL_ERROR", | |
| "message": "An internal server error occurred" | |
| } | |
| } | |
| ) | |
| # Initialize logging | |
| setup_logging() |