90 lines
2.3 KiB
Python
90 lines
2.3 KiB
Python
from contextlib import asynccontextmanager
|
|
from pathlib import Path
|
|
|
|
from fastapi import APIRouter, Body, Depends, FastAPI, HTTPException
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.staticfiles import StaticFiles
|
|
from sqlalchemy import text
|
|
from sqlalchemy.orm import Session
|
|
|
|
from core.config import settings
|
|
from core.db import get_db
|
|
from core.loader import load_apps
|
|
from core.redis_client import redis_client
|
|
from core.security import require_admin
|
|
from core.settings_service import get_setting_cached, set_setting
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
loaded = load_apps(app)
|
|
app.state.loaded_apps = loaded
|
|
yield
|
|
|
|
|
|
app = FastAPI(title="Shopsystem API", lifespan=lifespan)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.cors_list,
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# Static uploads
|
|
upload_dir = Path(settings.UPLOAD_DIR)
|
|
upload_dir.mkdir(parents=True, exist_ok=True)
|
|
app.mount("/uploads", StaticFiles(directory=str(upload_dir)), name="uploads")
|
|
|
|
|
|
@app.get("/health")
|
|
def health(db: Session = Depends(get_db)):
|
|
db_ok = False
|
|
redis_ok = False
|
|
try:
|
|
db.execute(text("SELECT 1"))
|
|
db_ok = True
|
|
except Exception:
|
|
pass
|
|
try:
|
|
redis_ok = bool(redis_client.ping())
|
|
except Exception:
|
|
pass
|
|
return {
|
|
"ok": db_ok and redis_ok,
|
|
"env": settings.APP_ENV,
|
|
"db": db_ok,
|
|
"redis": redis_ok,
|
|
"apps": [m.name for m in getattr(app.state, "loaded_apps", [])],
|
|
}
|
|
|
|
|
|
# Core router — settings management (admin)
|
|
core_router = APIRouter()
|
|
|
|
|
|
@core_router.get("/settings/{key}")
|
|
def read_setting(key: str):
|
|
"""Public read — Redis-backed."""
|
|
v = get_setting_cached(key)
|
|
if v is None:
|
|
raise HTTPException(404, f"Setting {key} not found")
|
|
return {"key": key, "value": v}
|
|
|
|
|
|
@core_router.put("/settings/{key}")
|
|
def write_setting(
|
|
key: str,
|
|
body: dict = Body(...),
|
|
_: dict = Depends(require_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
if "value" not in body:
|
|
raise HTTPException(400, "Missing 'value' in body")
|
|
set_setting(db, key, body["value"])
|
|
return {"key": key, "value": body["value"]}
|
|
|
|
|
|
app.include_router(core_router, prefix="/api/core", tags=["core"])
|