151 lines
4.3 KiB
Python
151 lines
4.3 KiB
Python
"""
|
|
FastAPI Application Factory Module
|
|
|
|
This module provides functionality to create and configure a FastAPI application with:
|
|
- Custom OpenAPI schema configuration
|
|
- Security scheme configuration for Bearer authentication
|
|
- Automatic router registration
|
|
- Response class configuration
|
|
- Security requirements for protected endpoints
|
|
"""
|
|
|
|
from types import ModuleType
|
|
from typing import Any, Dict, List, Optional, Union
|
|
from fastapi import FastAPI, APIRouter
|
|
from fastapi.responses import JSONResponse, RedirectResponse
|
|
from fastapi.openapi.utils import get_openapi
|
|
from fastapi.routing import APIRoute
|
|
from AllConfigs.main import MainConfig as Config
|
|
from middleware.auth_middleware import MiddlewareModule
|
|
|
|
|
|
def setup_security_schema() -> Dict[str, Any]:
|
|
"""
|
|
Configure security schema for the OpenAPI documentation.
|
|
|
|
Returns:
|
|
Dict[str, Any]: Security schema configuration
|
|
"""
|
|
return {
|
|
"Bearer": {
|
|
"type": "http",
|
|
"scheme": "bearer",
|
|
"bearerFormat": "JWT",
|
|
"description": "Enter the token",
|
|
}
|
|
}
|
|
|
|
|
|
def configure_route_security(
|
|
path: str, method: str, schema: Dict[str, Any], protected_paths: List[str]
|
|
) -> None:
|
|
"""
|
|
Configure security requirements for a specific route.
|
|
|
|
Args:
|
|
path: Route path
|
|
method: HTTP method
|
|
schema: OpenAPI schema to modify
|
|
protected_paths: List of paths that require authentication
|
|
"""
|
|
if path in protected_paths:
|
|
if "paths" not in schema:
|
|
schema["paths"] = {}
|
|
|
|
if path not in schema["paths"]:
|
|
schema["paths"][path] = {}
|
|
|
|
if method not in schema["paths"][path]:
|
|
schema["paths"][path][method] = {}
|
|
|
|
schema["paths"][path][method]["security"] = [{"Bearer": []}]
|
|
|
|
|
|
def get_routers(routers_module: ModuleType) -> List[APIRouter]:
|
|
"""
|
|
Extract all routers from the routers module.
|
|
|
|
Args:
|
|
routers_module: Module containing router definitions
|
|
|
|
Returns:
|
|
List[APIRouter]: List of router instances
|
|
"""
|
|
routers = []
|
|
for attr_name in dir(routers_module):
|
|
attr = getattr(routers_module, attr_name)
|
|
if isinstance(attr, APIRouter):
|
|
routers.append(attr)
|
|
return routers
|
|
|
|
|
|
def create_app(routers: ModuleType) -> FastAPI:
|
|
"""
|
|
Create and configure a FastAPI application.
|
|
|
|
Args:
|
|
routers: Module containing router definitions
|
|
|
|
Returns:
|
|
FastAPI: Configured FastAPI application instance
|
|
"""
|
|
# Initialize FastAPI app
|
|
app = FastAPI(
|
|
title=Config.TITLE,
|
|
description=Config.DESCRIPTION,
|
|
default_response_class=JSONResponse,
|
|
)
|
|
|
|
# Add home route that redirects to API documentation
|
|
@app.get("/", include_in_schema=False, summary=str(Config.DESCRIPTION))
|
|
async def home() -> RedirectResponse:
|
|
"""Redirect root path to API documentation."""
|
|
return RedirectResponse(url="/docs")
|
|
|
|
# Get all routers
|
|
router_instances = get_routers(routers)
|
|
|
|
# Find protected paths
|
|
protected_paths = []
|
|
for router in router_instances:
|
|
for route in router.routes:
|
|
if isinstance(route, APIRoute):
|
|
# Check if the route has auth_required decorator
|
|
if any(d.__name__ == "auth_required" for d in route.dependencies):
|
|
protected_paths.append(route.path)
|
|
|
|
# Include routers
|
|
for router in router_instances:
|
|
app.include_router(router)
|
|
|
|
# Configure custom OpenAPI schema
|
|
def custom_openapi():
|
|
if app.openapi_schema:
|
|
return app.openapi_schema
|
|
|
|
openapi_schema = get_openapi(
|
|
title=Config.TITLE,
|
|
version="1.0.0",
|
|
description=Config.DESCRIPTION,
|
|
routes=app.routes,
|
|
)
|
|
|
|
# Add security schemes
|
|
openapi_schema["components"] = {"securitySchemes": setup_security_schema()}
|
|
|
|
# Configure security for each route
|
|
for route in app.routes:
|
|
if isinstance(route, APIRoute):
|
|
configure_route_security(
|
|
route.path,
|
|
route.methods.pop().lower(),
|
|
openapi_schema,
|
|
protected_paths,
|
|
)
|
|
|
|
app.openapi_schema = openapi_schema
|
|
return app.openapi_schema
|
|
|
|
app.openapi = custom_openapi
|
|
return app
|