d5a270f3af
- backend/logging_setup.py: setup_logging() (stdout INFO + файл /tmp/vector/vector.log,
ротация 5×2 МБ, VectorLOGLEVEL/VectorLOGFILE/VectorLOGDIR), get_logger('vector.*')
- события: vector.analyze (матрасчёт с длительностью), vector.auth (login_ok/failed/
lockout), vector.audit (каждая запись), vector.contour (ok/failed/rejected),
vector.operations (operation_complete), vector.geocode (успех/timeout/ошибка)
- существующие логгеры переведены в namespace vector.* (geo, geo.osm, rules, water, admin)
- README §13а: таблица наблюдаемых событий + правила (без ПДн/секретов)
- SETUP_GUIDE: §15 RPO/RTO + backup≠restore, §16 grep по vector.*, §17 диагностика
по цепочкам (БД, 500, fallback-зоны, вход), §17а чек-лист передачи проекта
- DEPLOY.md: вместо устаревшего дубля — ссылка на актуальные доки + шпаргалка стенда
- тесты: 239 passed
75 lines
2.4 KiB
Python
75 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
import os
|
|
from contextlib import asynccontextmanager
|
|
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
from backend.database import init_db
|
|
from backend.logging_setup import setup_logging
|
|
from backend.routers.admin import router as admin_router
|
|
from backend.routers.admin_users import router as admin_users_router
|
|
from backend.routers.operations import router as operations_router
|
|
from backend.routers.contour import router as contour_router
|
|
from backend.routers.analyze import router as analyze_router
|
|
from backend.routers.auth import router as auth_router
|
|
from backend.routers.cases import router as cases_router
|
|
from backend.routers.closed_cases import router as closed_cases_router
|
|
from backend.routers.geocode import router as geocode_router
|
|
from backend.routers.health import router as health_router
|
|
from backend.routers.stats import router as stats_router
|
|
from backend.routers.water import router as water_router
|
|
|
|
|
|
def _parse_origins(value: str) -> list[str]:
|
|
origins = [origin.strip() for origin in value.split(',') if origin.strip()]
|
|
return origins or ['http://localhost:3000', 'http://127.0.0.1:3000']
|
|
|
|
|
|
cors_origins = _parse_origins(os.getenv('CORS_ORIGINS', 'http://localhost:3000,http://127.0.0.1:3000'))
|
|
allow_credentials = os.getenv('CORS_ALLOW_CREDENTIALS', 'true').strip().lower() in {'1', 'true', 'yes', 'on'}
|
|
if '*' in cors_origins:
|
|
allow_credentials = False
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
setup_logging()
|
|
log = logging.getLogger('vector.app')
|
|
log.info('Vector API стартует: CORS=%s', ','.join(cors_origins))
|
|
init_db()
|
|
yield
|
|
log.info('Vector API остановлен')
|
|
|
|
|
|
app = FastAPI(title='Vector API', version='0.1.0', lifespan=lifespan)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=cors_origins,
|
|
allow_credentials=allow_credentials,
|
|
allow_methods=['*'],
|
|
allow_headers=['*'],
|
|
)
|
|
|
|
|
|
app.include_router(health_router)
|
|
app.include_router(auth_router)
|
|
app.include_router(analyze_router)
|
|
app.include_router(cases_router)
|
|
app.include_router(closed_cases_router)
|
|
app.include_router(stats_router)
|
|
app.include_router(admin_router)
|
|
app.include_router(admin_users_router)
|
|
app.include_router(operations_router)
|
|
app.include_router(contour_router)
|
|
app.include_router(water_router)
|
|
app.include_router(geocode_router)
|
|
|
|
|
|
@app.get('/')
|
|
def root() -> dict[str, str]:
|
|
return {'name': 'Vector API', 'status': 'ok'}
|