Add config API endpoints and tests; update docs

This commit is contained in:
2025-10-14 21:45:30 +02:00
parent 52b96da8dc
commit 6b979eb57a
3 changed files with 114 additions and 0 deletions

68
src/server/api/config.py Normal file
View File

@@ -0,0 +1,68 @@
from typing import Optional
from fastapi import APIRouter, Depends, HTTPException, status
from src.config.settings import settings
from src.server.models.config import AppConfig, ConfigUpdate, ValidationResult
from src.server.utils.dependencies import require_auth
router = APIRouter(prefix="/api/config", tags=["config"])
@router.get("", response_model=AppConfig)
def get_config(auth: Optional[dict] = Depends(require_auth)) -> AppConfig:
"""Return current application configuration (read-only)."""
# Construct AppConfig from pydantic-settings where possible
cfg_data = {
"name": getattr(settings, "app_name", "Aniworld"),
"data_dir": getattr(settings, "data_dir", "data"),
"scheduler": getattr(settings, "scheduler", {}),
"logging": getattr(settings, "logging", {}),
"backup": getattr(settings, "backup", {}),
"other": getattr(settings, "other", {}),
}
try:
return AppConfig(**cfg_data)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to read config: {e}")
@router.put("", response_model=AppConfig)
def update_config(update: ConfigUpdate, auth: dict = Depends(require_auth)) -> AppConfig:
"""Apply an update to the configuration and return the new config.
Note: persistence strategy for settings is out-of-scope for this task.
This endpoint updates the in-memory Settings where possible and returns
the merged result as an AppConfig.
"""
# Build current AppConfig from settings then apply update
current = get_config(auth)
new_cfg = update.apply_to(current)
# Mirror some fields back into pydantic-settings 'settings' where safe.
# Avoid writing secrets or unsupported fields.
try:
if new_cfg.data_dir:
setattr(settings, "data_dir", new_cfg.data_dir)
# scheduler/logging/backup/other kept in memory only for now
setattr(settings, "scheduler", new_cfg.scheduler.model_dump())
setattr(settings, "logging", new_cfg.logging.model_dump())
setattr(settings, "backup", new_cfg.backup.model_dump())
setattr(settings, "other", new_cfg.other)
except Exception:
# Best-effort; do not fail the request if persistence is not available
pass
return new_cfg
@router.post("/validate", response_model=ValidationResult)
def validate_config(cfg: AppConfig, auth: dict = Depends(require_auth)) -> ValidationResult:
"""Validate a provided AppConfig without applying it.
Returns ValidationResult with any validation errors.
"""
try:
return cfg.validate()
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))