import logging from contextlib import asynccontextmanager import cloudinary import sys from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from .config import get_settings from .database import get_collection, test_connection from .routers import auth, incidents, policies # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.StreamHandler(sys.stdout) ] ) logger = logging.getLogger(__name__) async def setup_database_indexes(): """Set up database indexes with error handling.""" try: # Test connection first connection_ok = await test_connection() if not connection_ok: logger.warning("Database connection failed - skipping index creation") return # Create indexes users = get_collection("users") incidents_collection = get_collection("incidents") policies_collection = get_collection("policies") await users.create_index("email", unique=True) await incidents_collection.create_index("created_at") await policies_collection.create_index("created_at") await policies_collection.create_index("status") await policies_collection.create_index("category") logger.info("Database indexes created successfully") except Exception as e: logger.warning(f"Database setup failed: {e}") logger.warning("Application will continue without database indexes") @asynccontextmanager async def lifespan(app: FastAPI): # Startup settings = get_settings() # Initialize Cloudinary try: # Use environment variables from settings cloudinary.config( cloud_name=settings.cloudinary_cloud_name, api_key=settings.cloudinary_api_key, api_secret=settings.cloudinary_api_secret, secure=True ) logger.info("Cloudinary initialized successfully with cloud name: %s", settings.cloudinary_cloud_name) except Exception as e: logger.error(f"Cloudinary initialization failed: {e}") await setup_database_indexes() yield # Shutdown (if needed in future) settings = get_settings() app = FastAPI(title=settings.app_name, lifespan=lifespan) allowed_origins = settings.allowed_origins if isinstance(allowed_origins, str): allowed_origins = [origin.strip() for origin in allowed_origins.split(",") if origin.strip()] # Ensure we have the allowed origins for development and production if not allowed_origins: allowed_origins = ["*"] # Fallback to allow all if not configured app.add_middleware( CORSMiddleware, allow_origins=allowed_origins, allow_credentials=True, allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"], allow_headers=["*"], expose_headers=["*"], ) # Debug: Log the allowed origins in startup logger.info(f"CORS allowed origins: {allowed_origins}") @app.get("/health") async def health_check(): connection_ok = await test_connection() if connection_ok: return {"status": "ok", "database": "connected"} else: return {"status": "degraded", "database": "disconnected"} @app.get("/") async def root(): return {"message": "Marine Guard API", "status": "running"} @app.options("/{path:path}") async def options_handler(path: str): """Handle CORS preflight requests.""" return {"message": "OK"} app.include_router(auth.router, prefix="/api") app.include_router(incidents.router, prefix="/api") app.include_router(policies.router, prefix="/api")