Files
news_all_spo/api/main.py
2026-05-13 19:05:07 +05:00

83 lines
2.7 KiB
Python

import os
import secrets
from contextlib import asynccontextmanager
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from fastapi.middleware.cors import CORSMiddleware
from bd.database import wait_for_db, engine, Base
from route.public import router as public_router
from route.admin_auth import router as auth_router, ensure_default_admin
from route.admin_articles import router as articles_router
from route.admin_categories import router as categories_router
from route.admin_media import router as media_router
DOCS_USER = os.getenv("DOCS_USERNAME", "admin")
DOCS_PASS = os.getenv("DOCS_PASSWORD", "admin")
_basic = HTTPBasic()
def _verify_docs(creds: HTTPBasicCredentials = Depends(_basic)):
ok_u = secrets.compare_digest(creds.username.encode(), DOCS_USER.encode())
ok_p = secrets.compare_digest(creds.password.encode(), DOCS_PASS.encode())
if not (ok_u and ok_p):
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, headers={"WWW-Authenticate": "Basic"})
return creds.username
@asynccontextmanager
async def lifespan(app: FastAPI):
await wait_for_db()
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
await ensure_default_admin()
yield
app = FastAPI(
title="News API",
version="1.0.0",
lifespan=lifespan,
docs_url=None,
redoc_url=None,
openapi_url=None,
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
# Docs protected by HTTP Basic Auth
from fastapi.openapi.docs import get_swagger_ui_html, get_redoc_html
from fastapi.responses import JSONResponse
@app.get("/docs", include_in_schema=False)
async def docs(username: str = Depends(_verify_docs)):
return get_swagger_ui_html(openapi_url="/openapi.json", title="News API Docs")
@app.get("/redoc", include_in_schema=False)
async def redoc(username: str = Depends(_verify_docs)):
return get_redoc_html(openapi_url="/openapi.json", title="News API Redoc")
@app.get("/openapi.json", include_in_schema=False)
async def openapi(username: str = Depends(_verify_docs)):
return JSONResponse(app.openapi())
app.include_router(public_router, prefix="/news", tags=["public"])
app.include_router(auth_router, prefix="/admin", tags=["admin-auth"])
app.include_router(articles_router, prefix="/admin/articles", tags=["admin-articles"])
app.include_router(categories_router, prefix="/admin/categories", tags=["admin-categories"])
app.include_router(media_router, prefix="/admin/media", tags=["admin-media"])
if __name__ == "__main__":
import uvicorn
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=False)