Files
kadence/backend/app/api/routes_settings.py
T
timka123 d280101bce
docker / image (push) Failing after 24s
lint / ruff (push) Failing after 28s
tests / backend (push) Successful in 37s
tests / desktop (push) Successful in 22s
tests / android-core (push) Successful in 49s
tests / web (push) Successful in 1m20s
android / apk (push) Successful in 8m49s
disallow to disable guard during focus
2026-10-28 09:50:58 +03:00

62 lines
2.2 KiB
Python

"""Settings endpoints.
The browser never sees a real token: `GET` masks every secret, and a `PUT` that
sends the mask back untouched keeps the stored value.
"""
from __future__ import annotations
import json
from typing import Any
from fastapi import APIRouter, Body, HTTPException
from pydantic import ValidationError
from app.api.deps import DbSession, Settings
from app.services import blocker_service, settings_service
from app.settings_schema import AppSettings
router = APIRouter(prefix="/api/settings", tags=["settings"])
@router.get("")
def get_settings(settings: Settings) -> dict:
return {
"settings": settings_service.mask_secrets(settings.model_dump(mode="json")),
"defaults": {
"blocked_domains": blocker_service.DEFAULT_DOMAINS,
"blocked_apps": blocker_service.DEFAULT_APPS,
},
}
@router.put("")
def put_settings(session: DbSession, patch: dict[str, Any] = Body(...)) -> dict:
try:
updated = settings_service.apply_patch(session, patch)
except ValidationError as exc:
# `exc.errors()` can carry exception objects in `ctx`, which JSON cannot
# take; pydantic's own `json()` renders them as text.
raise HTTPException(status_code=422, detail=json.loads(exc.json())) from exc
except blocker_service.GuardLocked as exc:
# 409, not 422: the body is valid, the current state refuses it. A plain
# string detail is what every client's error path already surfaces.
raise HTTPException(status_code=409, detail=str(exc)) from exc
return {"settings": settings_service.mask_secrets(updated.model_dump(mode="json"))}
@router.post("/reset")
def reset_settings(session: DbSession) -> dict:
"""Back to defaults, re-seeded from the environment."""
try:
updated = settings_service.reset_to_env(session)
except blocker_service.GuardLocked as exc:
raise HTTPException(status_code=409, detail=str(exc)) from exc
return {"settings": settings_service.mask_secrets(updated.model_dump(mode="json"))}
@router.get("/schema")
def settings_schema() -> dict:
"""The JSON Schema, so a client can render the settings form generically."""
return AppSettings.model_json_schema()