feat: API gateway with passkey (WebAuthn) authentication
This commit is contained in:
parent
f218865872
commit
e0d138c457
9 changed files with 907 additions and 2 deletions
81
services/api_gateway/main.py
Normal file
81
services/api_gateway/main.py
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
"""FastAPI application — API Gateway for the trading bot."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import AsyncIterator
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from redis.asyncio import Redis
|
||||
|
||||
from services.api_gateway.auth.routes import router as auth_router
|
||||
from services.api_gateway.config import ApiGatewayConfig
|
||||
from shared.db import create_db
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def create_app(config: ApiGatewayConfig | None = None) -> FastAPI:
|
||||
"""Build and configure the FastAPI application.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
config:
|
||||
Optional config override (useful for testing). If ``None``, a new
|
||||
:class:`ApiGatewayConfig` is created from environment variables.
|
||||
"""
|
||||
if config is None:
|
||||
config = ApiGatewayConfig()
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
||||
"""Start-up / shutdown hook — connect DB and Redis."""
|
||||
# Database
|
||||
engine, session_factory = create_db(config)
|
||||
app.state.db_engine = engine
|
||||
app.state.db_session_factory = session_factory
|
||||
|
||||
# Redis
|
||||
app.state.redis = Redis.from_url(
|
||||
config.redis_url, decode_responses=True
|
||||
)
|
||||
app.state.config = config
|
||||
|
||||
logger.info("API Gateway started")
|
||||
yield
|
||||
|
||||
# Cleanup
|
||||
await app.state.redis.aclose()
|
||||
await engine.dispose()
|
||||
logger.info("API Gateway stopped")
|
||||
|
||||
app = FastAPI(
|
||||
title="Trading Bot API",
|
||||
version="0.1.0",
|
||||
lifespan=lifespan,
|
||||
)
|
||||
|
||||
# CORS
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=config.cors_origins,
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
# Auth routes (unauthenticated)
|
||||
app.include_router(auth_router)
|
||||
|
||||
# Health check
|
||||
@app.get("/health", tags=["health"])
|
||||
async def health() -> dict:
|
||||
return {"status": "ok"}
|
||||
|
||||
return app
|
||||
|
||||
|
||||
# Convenience: allow ``uvicorn services.api_gateway.main:app``
|
||||
app = create_app()
|
||||
Loading…
Add table
Add a link
Reference in a new issue