from __future__ import annotations from secrets import compare_digest from typing import Annotated from fastapi import Depends, FastAPI, HTTPException, status from fastapi.middleware.cors import CORSMiddleware from fastapi.openapi.docs import get_swagger_ui_html from fastapi.security import HTTPBasic, HTTPBasicCredentials from cpv3.api.v1.router import api_router from cpv3.infrastructure.settings import get_settings ERROR_SWAGGER_AUTH_INVALID = "Invalid Swagger credentials" settings = get_settings() swagger_security = HTTPBasic() app = FastAPI( title="Coffee Project Backend API", version="0.0.0", openapi_url=None, docs_url=None, redoc_url=None, ) app.add_middleware( CORSMiddleware, allow_origins=settings.cors_allowed_origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) def verify_swagger_auth( credentials: Annotated[HTTPBasicCredentials, Depends(swagger_security)], ) -> None: login_matches = compare_digest( credentials.username, settings.swagger_auth_login, ) password_matches = compare_digest( credentials.password, settings.swagger_auth_password, ) if not settings.swagger_auth_login or not settings.swagger_auth_password: login_matches = False password_matches = False if not login_matches or not password_matches: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_SWAGGER_AUTH_INVALID, headers={"WWW-Authenticate": "Basic"}, ) @app.get("/api/schema/", include_in_schema=False) async def openapi_schema( _: Annotated[None, Depends(verify_swagger_auth)], ): return app.openapi() @app.get("/api/schema/swagger/", include_in_schema=False) async def swagger_ui( _: Annotated[None, Depends(verify_swagger_auth)], ): return get_swagger_ui_html( openapi_url="/api/schema/", title="Coffee Project Backend API - Swagger UI", ) # Include the versioned API router app.include_router(api_router)