add user? new page? new web

This commit is contained in:
2026-03-23 21:28:10 +05:00
parent 04bfff3d3f
commit 9cd6d83428
26 changed files with 917 additions and 65 deletions

58
main.py
View File

@@ -1,14 +1,17 @@
import os
import secrets
import tomllib
from pathlib import Path
from fastapi import FastAPI
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.openapi.docs import get_redoc_html, get_swagger_ui_html
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from route import base, holland_crud, init_data_base, groups_crud, organizations_crud, users_crud, question_crud, choice_crud, response_crud, poll_crud
from route import auth
import uvicorn
# Читаем версию из pyproject.toml
try:
# Получаем абсолютный путь к pyproject.toml
pyproject_path = Path(__file__).parent / "pyproject.toml"
with open(pyproject_path, "rb") as f:
pyproject = tomllib.load(f)
@@ -17,18 +20,45 @@ except Exception as e:
print(f"Warning: Could not read version from pyproject.toml: {e}")
VERSION = "0.1.0"
# Читаем переменные окружения
APP_PATH = os.getenv("APP_PATH", "/home/user/api-copp")
app = FastAPI(title="api", version=VERSION)
# ---------------------------------------------------------------------------
# Защита документации HTTP Basic Auth
# ---------------------------------------------------------------------------
_basic = HTTPBasic()
def _verify_docs(credentials: HTTPBasicCredentials = Depends(_basic)):
"""Проверяет логин/пароль для доступа к /docs и /redoc."""
docs_user = os.getenv("DOCS_USERNAME", "")
docs_pass = os.getenv("DOCS_PASSWORD", "")
if not docs_user or not docs_pass:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail="API docs are disabled: DOCS_USERNAME / DOCS_PASSWORD not configured",
)
# secrets.compare_digest защищает от timing-атак (перебора по времени ответа)
ok_user = secrets.compare_digest(credentials.username.encode(), docs_user.encode())
ok_pass = secrets.compare_digest(credentials.password.encode(), docs_pass.encode())
if not (ok_user and ok_pass):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid credentials",
headers={"WWW-Authenticate": "Basic"},
)
# docs_url/openapi_url/redoc_url отключены — добавляем защищённые маршруты вручную
app = FastAPI(title="api", version=VERSION, docs_url=None, openapi_url=None, redoc_url=None)
# Разрешаем CORS для фронтенда (dev). При необходимости сузить список origins.
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000", "http://127.0.0.1:3000"],
allow_origins=["http://localhost", "http://127.0.0.1"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(auth.router)
app.include_router(base.router)
app.include_router(init_data_base.router)
app.include_router(groups_crud.router)
@@ -41,8 +71,24 @@ app.include_router(poll_crud.router)
app.include_router(holland_crud.router)
# ---------------------------------------------------------------------------
# Защищённые маршруты документации
# ---------------------------------------------------------------------------
@app.get("/docs", include_in_schema=False)
def get_docs(_: None = Depends(_verify_docs)):
return get_swagger_ui_html(openapi_url="/openapi.json", title="API Docs")
@app.get("/redoc", include_in_schema=False)
def get_redoc(_: None = Depends(_verify_docs)):
return get_redoc_html(openapi_url="/openapi.json", title="API Docs")
@app.get("/openapi.json", include_in_schema=False)
def get_openapi_schema(_: None = Depends(_verify_docs)):
return app.openapi()
# Доступна переменная APP_PATH для использования в приложении
print(f"Application path: {APP_PATH}")
if __name__ == "__main__":